У меня есть файл с пустыми строками в конце файла. Можно ли использовать grepдля подсчета количества пустых строк в конце файла с именем файла, передаваемым в сценарии как переменная?
grep@MichaelJohn за чистоту в моей книге.
У меня есть файл с пустыми строками в конце файла. Можно ли использовать grepдля подсчета количества пустых строк в конце файла с именем файла, передаваемым в сценарии как переменная?
grep@MichaelJohn за чистоту в моей книге.
Ответы:
Если пустые строки только в конце
grep -c '^$' myFile
или же:
grep -cx '' myFile
grep -cv . myFileэто еще один способ написать это (для игроков в гольф код). Но я нашел решение, grepесли в файле есть пустые строки.
grep -cv .также будет считать строки, содержащие только байты, которые не образуют допустимых символов.
Просто для удовольствия, некоторые привидение 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.Еще несколько 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 '.
Поскольку вы на самом деле запрашиваете grepрешение, я добавляю это, полагаясь только на GNU grep(хорошо, также используя синтаксис оболочки и echo...):
#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))
Что я здесь делаю? $(grep -c ".*" "$1")считает все строки в файле, затем вычитает файл без конечных пустых строк.
И как их получить? $(grep -B42 . "$1"будет обрабатывать все непустые строки и 42 строки перед ними, поэтому он будет печатать все до последней непустой строки, если перед непустой строкой находится не более 42 последовательных пустых строк. Чтобы избежать этого ограничения, я принимаю $(grep -cv . "$1")в качестве параметра для -Bопции, которая является общим количеством пустых строк, поэтому всегда достаточно большой. Таким образом, я убрал конечные пустые строки и могу использовать их |grep -c ".*"для подсчета строк.
Блестящий, не правда ли? (-;
tac | grepпервый непустой с -m -A 42, затем минус один. Я не уверен, что является более эффективным, но вы также могли бы wc -l | cut -d' ' -f1вместо того, чтобы вырезать пустые строки?
tac, wcи cut, но здесь я пытался ограничиться grep. Вы можете назвать это извращением, я называю это спортом. (-;
Другое awkрешение. Этот вариант сбрасывает счетчик kкаждый раз, когда появляется непустая строка. Затем каждая строка увеличивает счетчик. (Итак, после первой непустой строки длины k==0.) В конце мы выводим количество пересчитанных нами строк.
Подготовьте файл данных
cat <<'X' >input.txt
aaa
bbb
ccc
X
Подсчитайте конечные пустые строки в образце
awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3
В этом определении пустая строка может содержать пробелы или другие пустые символы; это все еще пусто Если вы действительно хотите считать пустые строки, а не пустые, измените NFна $0 != "".
$0 > ""? Использует то, strcoll()что было бы менее эффективно, чем то, $0 != ""которое используется memcmp()во многих реализациях (POSIX раньше требовал его использования, strcoll()хотя).
$0 > ""может отличаться $0 != "". В awkлюбом случае я склонен относиться к «медленным» операторам (например, если я знаю, что у меня большой ввод данных в качестве входных данных, а обработка критична по времени, я посмотрю, что можно сделать, чтобы уменьшить объем awkобработки - я использовали grep | awkконструкции в таких ситуациях). Тем не менее, имея быстрый взгляд на то , что я предполагаю , что это определение POSIX я не вижу каких - либо ссылок на любой strcoll()или memcmp(). Что мне не хватает?
strcoll()== строки должны сравниваться с использованием последовательности сопоставления для конкретной локали . Сравните с предыдущим изданием . Я был тем, кто поднял это. См. Также austingroupbugs.net/view.php?id=963
a <= b && a >= bне обязательно совпадает с a == b. Ой!
awkили bash(для его [[ a < b ]]операторов) в en_US.UTF-8 локалей в системах GNU, например , для ①против ②, например (для bash, ни один из <, >, =возвращает истину для тех , кто). Возможно, это ошибка в определении этих локалей больше, чем в bash / awk
подсчитать количество последовательных пустых строк в конце файла
Твердый awk+ tacраствор:
Образец input.txt:
$ cat input.txt
aaa
bbb
ccc
$ # command line
Действие:
awk '!NF{ if (NR==++c) { cnt++ } else exit }END{ print int(cnt) }' <(tac input.txt)
!NF- гарантирует, что текущая строка пуста (не имеет полей)NR==++c- обеспечение последовательного порядка пустых строк. ( NR- номер записи, ++c- равномерно увеличенный вспомогательный счетчик)cnt++- счетчик пустых строкВыход:
3
IIUC, следующий скрипт вызвал count-blank-at-the-end.shбы работу:
#!/usr/bin/env sh
count=$(tail -n +"$(grep . "$1" -n | tail -n 1 | cut -d: -f1)" "$1" | wc -l)
num_of_blank_lines=$((count - 1))
printf "%s\n" "$num_of_blank_lines"
Пример использования:
$ ./count-blank-at-the-end.sh FILE
4
Я тестировал его в GNU bash, Android mkshи ksh.
Альтернативное Pythonрешение:
Пример input.txt:
$ cat input.txt
aaa
bbb
ccc
$ # command line
Действие:
python -c 'import sys, itertools; f=open(sys.argv[1]);
lines=list(itertools.takewhile(str.isspace, f.readlines()[::-1]));
print(len(lines)); f.close()' input.txt
Выход:
3
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile