У меня есть файл с пустыми строками в конце файла. Можно ли использовать 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