Як я можу видалити 5-е слово кожного рядка з файлу?


13

Я хочу видалити 5-е слово кожного рядка у файлі.

Поточний вміст файлу:

File is not updated or and will be removed  
System will shut down f within 10 seconds  
Please save your work 55 or copy to other location  
Kindly cooperate with us D  

Очікуваний вихід:

File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us

Відповіді:


31

Як щодо cut:

$ cut -d' ' -f1-4,6- file.txt 
File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us
  • -d' ' встановлює роздільник як пробіл

  • -f1-4,6- вибирає перше-четверте поле (слово), залишаючи 5-е, а потім продовжуємо друкувати з 6-го на решту.


11

Рішення з cut:

cut -d ' ' -f1-4 -f6- FILE

Кілька -fне підтримується в моєму cut(GNU) принаймні ..
heemayl

Підтримується в скороченні BSD, але мені подобається ваша відповідь краще, ніж моя.
fd0

1
Якщо це GNU вирізати, ви отримаєте --complementпрапор , щоб спростити речі: cut --complement -d ' ' -f5. Не забудьте перенаправити вихід на новий файл, а потім mvнад оригіналом.
Toby Speight

6

awk: видалити 5-е поле

awk '{for (i=5; i<NF; i++) $i = $(i+1); NF--};1' file

Якщо ви хочете зберегти файл на місці: /programming//q/16529716/7552

Ви можете просто стерти вміст 5-го поля, але це залишає 2 послідовних роздільника вихідних полів:

awk '{$5 = ""};1' file

Застереження тут полягає в тому, що зміна значення будь-якого поля в awk має побічний ефект переписування цілого "$ 0", лише 1 роздільник між полями. слід враховувати, якщо ви хочете зберегти будь-яке вирівнювання (якщо тільки у gnu awk немає можливості цього уникнути? регулярні awk / nawk будуть перераховувати $ 0)
Олів'є Дулак

В обох випадках ви переформатуєте рядок за допомогою одного роздільника. Якщо в розділювачі є 2 пробіли або пробіл + вкладка, результат - єдиний пробіл на місці. Це з надією добре для більшої частини тексту.
NeronLeVelu

4

З POSIX sed:

sed -e 's/[^[:alnum:]_][[:alnum:]_][[:alnum:]_]*//4' <file

навіщо обмежувати клас: alnum: і _ нічим іншим тоді :blank:чи :space:?
NeronLeVelu

@NeronLeVelu: Це залежить від того, як ви визначаєте, що складати слово.
cuonglm

@mikeserv; Приємний улов! Я оновив свою відповідь.
cuonglm

Для чого \(група захоплення \)?
mikeserv

@mikeserv: моє неправильне введення тексту, я просто спробував кілька способів зберегти роздільник.
cuonglm

2

Гленн запропонував рішення, рівнозначне

awk '{$ 5 = ""; print} ' файл

Як він та інші вказували, це

  1. смуги, що ведуть і проміжно пробіл з кожного рядка,
  2. стискає кожен рядок пробілів (пробіли та / або вкладки) в єдиний пробіл, і
  3. залишає два проміжки між четвертим та шістьма словами.

Злому, щоб виправити третю проблему

awk '{$ 5 = ""; print} ' файл | sed 's / / /'

Це все одно залишить одне або більше доданих пробілів у кінці будь-якого рядка, на якому міститься п'ять чи менше слів. Якщо ви зможете визначити слово, яке ніколи не відображатиметься на вводі,

awk '{$ 5 = "єдиноріг"; print} ' файл | sed 's / * єдиноріг //'

впорається навіть з цим (але це все ще залишає проблеми 1 і 2).


2
 sed 's/^\(\([[:blank:]]*[^[:blank:]]\{1,\}\)\{4\}\)[[:blank:]]*[^[:blank:]]*/\1/' YourFile > Output.txt
  • posix sed на основі роздільника простору / вкладки (мета-клас [: blank:]])
  • збережіть наступний пробіл після 5-го слова, але видаляючи попереднє

Більш надійний (sed взяв найдовший можливий візерунок і шаблон з *може пропустити розділення або слово в першій версії), але трохи довший варіант

sed 's/^\([[:blank:]]*\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{4\}\[^[:blank:]]\{1,\}/\1/' YourFile > Output.txt

1
sed 's/[^[:blank:]]*//5'
mikeserv

@mikeserv, це дозволить зберегти обидва оточуючих роздільника sed 's/[[:blank:]*[^[:blank:]]*//5'. Дуже хороший момент. Я підозрював, що sed сприймає кожну символіку як сутність, але вона має найбільшу непорушену картину як сутність
NeronLeVelu

sed 's/[[:blank:]][^[:blank:]]*//4'буде видалено 5-е поле повністю.
mikeserv

@mikeserv Припускаючи, що на лінії немає стартового простору (як у зразку)
NeronLeVelu

У цьому випадку, так, я думаю, ви праві. Зазвичай така річ буде нульовим полем, і поведінка буде правильною. В цьому випадку ви повинні зробити , як @cuonglm зробив , і переконайтеся , що ви посилаєтеся на слово кожен раз , як sed 's/[[:blank:]][^[:blank:]][^[:blank:]]*//4', або, ж / GNU / BSD / Іграшкові seds: sed -E 's/[[:blank:]][^[:blank:]]+//4'.
mikeserv



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.