Як видалити порожні рядки, починаючи з 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 до кінця введення ( $) виконувати наступні команди до відповідності }". Команди між {і }знову можуть бути встановлені за адресами, тому внутрішня команда /^$/dозначає "якщо між початком ( ^) і кінцем ( $) рядка немає нічого , видаліть його". Команди sed можна розділити на ;. (Це погано задокументована функція sed. Це підтримується більшістю реалізацій sed, але це не зовсім портативно .) Як зазначає Hauke, ;після не {є обов'язковим; той, хто раніше }, потрібен.

Якщо ви хочете видалити всі порожні рядки, починаючи з рядка 5, а також видалити рядки від 1 до 4, це простіше:

sed -i '1,4d;/^$/d' temp_spec.rb

Приємно. Я не знав, що адреси можна вкладати таким чином. Для мене це працює і без ведучих ;.
Hauke ​​Laging

Так, ти маєш рацію щодо першого ;.
Уве

@Hauke ​​Laging Ви можете відокремити команди в sed-скрипті на ';' замість того, щоб розмістити їх на окремих лініях. Це "недокументована" особливість.
Predrag Punosevac


2
sed '5,${s/^$//; t delete; b end; : delete; d; : end;}' temp_spec.rb

Редагувати 1:

Я повинен пояснити це, таким чином ...

Це зайво складно. Я не знав, що діапазони адрес дозволені в межах {}. Тому мені довелося виражати "видалити порожні рядки" по-різному. Основна команда полягає в тому, tяким є sed-шлях if ... then. Tбуло б простіше, але він доступний лише для GNU sed. Я цитую сторінку man:

t label: Якщо як /// здійснив успішну заміну з моменту зчитування останнього рядка вводу та з останньої команди t або T, то гілка на мітку; якщо мітка пропущена, відгалуження до кінця скрипту.

Я зловживаю відомою sкомандою. Він не замінить нічого, а лише перевірить, чи рядок порожній. Таким чином, він замінює порожній рядок порожнім рядком (може використовувати що-небудь як заміну, оскільки рядок все одно видаляється).

Якщо sви зробили "заміну", рядок порожній. У цьому випадку команда dвиконується. Інакше нічого не робити. Як tне скаче у випадку sдії, мені потрібна команда гілки, bщоб перейти до кінця сценарію. : labelє галузевими цілями. Як і gotoтоді, у темні віки (коли був винайдений sed ... хе-хе).

Іншим варіантом було б s«замінити» всі непусті рядки, що спростить sскладніші, але решта команди простіші:

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

^..*$означає "не порожній рядок" і \1означає "вміст перших дужок".


Трохи пояснень заради ОП (я можу відчути, як їхній мозок намагається виповзти через вуха, читаючи це ...)
vonbrand
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.