Как я могу удалить 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 Cut, но мне нравится ваш ответ лучше, чем мой.
fd0

1
Если это GNU вырезать, вы получите --complementфлаг , чтобы упростить вещи: cut --complement -d ' ' -f5. Не забудьте перенаправить вывод в новый файл, а затем mvповерх оригинала.
Тоби Спейт

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» только с одним разделителем между каждым полем. следует принять во внимание, если вы хотите сохранить какое-либо выравнивание (если у 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 = ""; печать} ' файл

Как он и другие указали, это

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

Взломать, чтобы исправить третью проблему

awk '{$ 5 = ""; печать} ' файл | sed 's / / /'

Это по-прежнему оставит один или несколько добавленных пробелов в конце любой строки, в которой вводится пять или менее слов. Если вы можете определить слово, которое никогда не появится на входе,

awk '{$ 5 = "единорог"; печать} ' файл | 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.