Как удалить пустые строки, начиная со строки 5

10

У меня есть это:

sed -i '/^$/d' temp_spec.rb

который удаляет пустые строки и работает хорошо. Как я могу сделать это только для строк 5-999 (или в идеале от 5 до конца файла).

Я старался:

sed -n5,999 -i '/^$/d' temp_spec.rb
sed '5,999!d/^$/d' temp_spec.rb

но ни один не работал (без ошибок).

Майкл Даррант
источник
Просто чтобы быть уверенным: Вы хотите сохранить строки с 1 по 4, независимо от того, являются ли они пустыми или нет, или вы хотите удалить строки с 1 по 4, независимо от того, являются ли они пустыми или нет? (До сих пор я предполагал первое, но вторая команда, которую вы попробовали, заставляет меня задуматься.)
Уве,

Ответы:

12

Если вы хотите удалить все пустые строки, начиная со строки 5 и оставить строки от 1 до 4, вы можете использовать

sed -i '5,${;/^$/d;}' temp_spec.rb

Это {оператор группировки, поэтому первая команда 5,${означает «от строки 5 до конца input ( $) выполнить следующие команды до совпадения }». Команды между {и }могут снова иметь префикс по адресам, поэтому внутренняя команда /^$/dозначает «если между строкой begin ( ^) и end ( $) строки ничего нет , удалите ее». Команды Sed могут быть разделены ;. (Это плохо документированная особенность sed. Она поддерживается большинством реализаций sed, но не полностью переносима .) Как отметил Хауке, ;after {не обязателен; один , прежде чем }требуется, однако.

Если вы хотите удалить все пустые строки, начиная со строки 5, а также удалить строки с 1 по 4, это проще:

sed -i '1,4d;/^$/d' temp_spec.rb
Uwe
источник
Приятно. Я не знал, что адреса могут быть вложены таким образом. Для меня это работает и без ведущего ;.
Хауке Лагинг
Да, вы правы насчет первого ;.
Уве
@ Hauke ​​Laging Вы можете разделять команды в сценарии sed с помощью ';' вместо этого помещая их в отдельные строки. Это «недокументированная» функция.
Предраг Пуносевац
4

Еще один вариант использования awk:

awk 'NR<5||/./'
LRI
источник
2
sed '5,${s/^$//; t delete; b end; : delete; d; : end;}' temp_spec.rb

Изменить 1:

Я должен объяснить это, таким образом ...

Это излишне сложно. Я не знал, что диапазоны адресов разрешены в пределах {}. Поэтому мне пришлось выразить «удалить пустые строки» по-другому. Основная команда - tэто способ sed if ... then. Tбыло бы проще, но доступно только для GNU sed. Я цитирую справочную страницу:

метка t: если as /// выполнила успешную замену после прочтения последней строки ввода и после последней команды t или T, то переход к метке; если метка опущена, переход к концу скрипта.

Я злоупотребляю знаменитой sкомандой. Он не должен ничего заменять, а только проверяет, пуста ли строка. Таким образом, он заменяет пустую строку пустой строкой (в качестве замены может использоваться что угодно, поскольку строка в любом случае удаляется).

Если sпроизведена «замена», то строка пуста. В этом случае команда dдолжна быть выполнена. Иначе ничего не поделаешь. Как tне прыгает в случае sдействия мне нужна команда bперехода, чтобы перейти к концу скрипта. : labelявляются целями филиала. Как gotoтогда, в темные века (когда был изобретен sed ... te-hee).

Другой вариант - s«заменить» все непустые строки, sупрощая более сложную, но остальную часть команды:

sed '5,${s/^\(..*\)$/\1/; t end; d; : end;}' input

^..*$означает «непустая строка» и \1означает «содержимое первых скобок».

Хауке Лагинг
источник
Немного объяснения ради OP (я чувствую, как их мозг пытается выползти через уши, читая это ...)
vonbrand