В поисках способа удаления пустых строк в начале и конце tac
файла (с помощью ) я наткнулся на это:
awk 'NF {p=1} p'
Как/почему это работает?
Я понимаю NF
, что это только true
если есть какие-либо поля (если строка не пустая).
решение1
Это удалит пустые строки в начале,но не с концафайла.[Примечание: этот ответ был написан доправка к вопросучто упомянуто tac
]
Работает это следующим образом:
NF
количество полей, найденных в текущей строке. Если оно равно нулю, это означает, что строка либо пустая, либопустой, т.е. содержит максимум пробелы (при условии, что разделитель полей оставлен в значении по умолчанию, где любое количество последовательных пробелов считается разделителем).- Текущая строка печатается, если любое условие вне (и не связанное с) блоков правил (
{ ... }
) оценивается какtrue
. Флагp
изначально не инициализирован и будет оцениваться какfalse
, поэтому априори ничего не будет напечатано. - Как только найдена непустая строка (
NF
отлична от нуля и оценивается какtrue
), блок правил{p=1}
вводится, и флагp
устанавливается в1
. После этогоp
внешняя часть блока правил оценивается какtrue
, и все последующие строки (включая текущую, первую непустую) печатаются.
Уведомлениечто поскольку флаг p
никогда не сбрасывается, любые пустые строки, следующие за первой непустой строкой, будут напечатаны без фильтрации. Если вы хотите удалить пустые строки и в конце, понадобится двухпроходный подход:
awk 'FNR==NR{if (NF) {if (!first) first=FNR; last=FNR} next}
FNR>=first && FNR<=last' input.txt input.txt
Это обработает файл дважды (поэтому он указан дважды как операнд)
- На первом проходе, где
FNR
счетчик строк для каждого файла равенNR
глобальному счетчику строк, мы определяем первую и последнюю непустую строку. - Во втором проходе (
FNR
теперь меньше, чемNR
) мы печатаем только строки между (включая) идентифицированными первой и последней непустыми строками.
Уведомление
Как указано вответ Стефана Шазеля, двухпроходный подход работает только с обычными файлами. Если ваш ввод имеет иную природу, см. предложенный там метод для решения.
решение2
Использование этого метода для удаления пустых строк из начала и конца файла:
awk 'NF {p=1} p' file | # remove blank lines at the file head
tac | # reverse the lines
awk 'NF {p=1} p' | # remove blanks from the "new head"
tac | # re-reverse the file
sponge file # from the `moreutils` package, to overwrite the file
решение3
Что делает ваш код и почему он удаляет только пустые строки в начале ввода, уже объяснялось в@AdminBee ответнапример, но здесь для полноты картины я предложу альтернативный метод удаления как начальных, так и конечных пустых строк без необходимости делать два прохода по файлу (что будет работать только для обычных файлов, а не для произвольного ввода).
awk '
NF {print saved $0; saved = ""; started = 1; next}
started {saved = saved $0 ORS}' < file
Где мы задерживаем печать пустых строк до следующей непустой строки, которую видим после этого (при условии, что мы уже видели хотя бы одну непустую строку ранее).
решение4
Если вы не против удаления пробелов и табуляций в пустых строках, которые вы хотите сохранить, это удалит пустые строки в начале и конце:
awk 'NF{for(;c;--c)print "";print;x=1;next} x{++c}'
Он подсчитывает количество пустых строк между непустыми строками и выводит это количество пустых строк перед каждой непустой строкой.