Подсчитайте количество пустых строк в конце файла.

Подсчитайте количество пустых строк в конце файла.

У меня есть файл с пустыми строками в конце файла. Могу ли я использовать grepдля подсчета количества пустых строк в конце файла, передавая имя файла как переменную в скрипте?

решение1

Если пустые строкитольков конце

grep  -c '^$' myFile

или:

grep -cx '' myFile

решение2

Просто ради забавы, немного жути sed:

#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l

Объяснение:

  • /./обращается к строкам с любым символом, поэтому /./!обращается к пустым строкам (например /^$/, , но я хочу повторно использовать противоположный шаблон); для них Hкоманда добавляет их в удерживаемое пространство. Таким образом, если для каждой пустой строки мы добавили одну строку в удерживаемое пространство, всегда будет на одну строку больше, чем пустых строк. Мы позаботимся об этом позже.
  • //hпустой шаблон соответствует последнему регулярному выражению, которое было любым символом, поэтому любая непустая строка рассматривается ивзолнованныйв удерживаемое пространство командой h«сброса» собранных строк до 1. Когда будет добавлена ​​следующая пустая строка, их снова будет две, как и ожидалось.
  • $!dостанавливает скрипт без вывода для каждой строки, кроме последней, поэтому дальнейшие команды выполняются только после последней строки. Поэтому все пустые строки, которые мы собрали в пространстве удержания, находятся в конце файла. Хорошо.
  • //d: dКоманда снова выполняется только для непустых строк. Так что если последняя строка не была пустой, то sedпроизойдет выход без вывода. Ноль строк. Хорошо.
  • xобмены занимают пространство и пространство шаблонов, поэтому собранные строки теперь находятся в пространстве шаблонов для обработки.
  • Но мы помним, что одна строка лишняя, поэтому сокращаем ее, удаляя одну новую строку с помощью s/\n//.
  • Вуаля! Количество строк совпадает с количеством пустых строк в конце (обратите внимание, что первая строка не будет пустой, но кого это волнует), поэтому мы можем посчитать их с помощью wc -l.

решение3

Еще несколько опций GNU tac/ tail -r:

tac file | awk 'NF{exit};END{print NR?NR-1:0}'

Или:

tac file | sed -n '/[^[:blank:]]/q;p' | wc -l

Обратите внимание, что на выходе:

printf 'x\n '

То есть, если после последней полной строки есть лишний пробел (который некоторые могут посчитать дополнительной пустой строкой, но по определению текста POSIX не является допустимым текстом), они вернут 0.

POSIXly:

awk 'NF{n=NR};END{print NR-n}' < file

но это означает чтение файла полностью ( tail -r/ tacбудет читать файл в обратном направлении с конца для файлов с возможностью поиска). Это дает 1на выходе printf 'x\n '.

решение4

Поскольку вы на самом деле проситеgrepрешениеЯ добавляю это, полагаясь только на GNU grep(ладно, также используя синтаксис оболочки и echo...):

#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))

Что я здесь делаю? $(grep -c ".*" "$1")подсчитывает все строки в файле, затем вычитает файл без конечных пустых строк.

И как их получить? $(grep -B42 . "$1"grep все непустые строки и 42 строки перед ними, так что он выведет все до последней непустой строки, пока не будет более 42 последовательных пустых строк перед непустой строкой. Чтобы избежать этого ограничения, я беру $(grep -cv . "$1")в качестве параметра для -Bопции, которая является общим количеством пустых строк, поэтому всегда достаточно большим. Таким образом я удалил конечные пустые строки и могу использовать |grep -c ".*"для подсчета строк.

Гениально, не правда ли? (-;

Связанный контент