
Eu tenho um arquivo com linhas em branco no final do arquivo. Posso usar grep
para contar o número de linhas em branco no final do arquivo com o nome do arquivo sendo passado como variável no script?
Responder1
Se as linhas em branco foremapenasno final
grep -c '^$' myFile
ou:
grep -cx '' myFile
Responder2
Apenas por diversão, alguns assustadores sed
:
#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l
Explicação:
/./
endereça linhas com qualquer caractere, portanto/./!
endereça linhas vazias (como/^$/
, mas quero reutilizar o padrão oposto); para esses, oH
comando os anexa ao espaço de espera. Assim, se para cada linha vazia adicionamos uma linha ao espaço de espera, sempre haverá uma linha a mais que o número de linhas vazias. Cuidaremos disso mais tarde.//h
o padrão vazio corresponde à última expressão regular, que era qualquer caractere, portanto, qualquer linha não vazia é endereçada emudou-separa o espaço de espera peloh
comando para "redefinir" as linhas coletadas para 1. Quando a próxima linha vazia for anexada, haverá duas novamente, como esperado.$!d
interrompe o script sem saída para cada linha, exceto a última linha, portanto, comandos adicionais são executados somente após a última linha. Portanto, quaisquer linhas vazias que coletamos no espaço de espera estão no final do arquivo. Bom.//d
: Od
comando é novamente executado apenas para linhas não vazias. Portanto, se a última linha não estiver vazia,sed
sairá sem nenhuma saída. Zero linhas. Bom.x
as trocas retêm espaço e espaço padrão, portanto, as linhas coletadas estão agora no espaço padrão para serem processadas.- Mas lembramos que há uma linha a mais, então a reduzimos removendo uma nova linha com
s/\n//
. - Voilà! O número de linhas corresponde ao número de linhas vazias no final (observe que a primeira linha não estará vazia, mas quem se importa), então podemos contá-las com
wc -l
.
Responder3
Mais algumas opções GNU tac
/ :tail -r
tac file | awk 'NF{exit};END{print NR?NR-1:0}'
Ou:
tac file | sed -n '/[^[:blank:]]/q;p' | wc -l
Observe que na saída de:
printf 'x\n '
Ou seja, onde houver um espaço extra após a última linha completa (que alguns poderiam considerar como uma linha extra em branco, mas pela definição POSIX de texto, não é um texto válido), isso daria 0.
POSIXamente:
awk 'NF{n=NR};END{print NR-n}' < file
mas isso significa ler o arquivo por completo ( tail -r
/ tac
leria o arquivo de trás para frente nos arquivos pesquisáveis). Isso dá 1
na saída de printf 'x\n '
.
Responder4
Como você está realmente pedindo umgrep
soluçãoEu adiciono este contando apenas com GNU grep
(ok, também usando sintaxe shell e echo
...):
#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))
O que estou fazendo aqui? $(grep -c ".*" "$1")
conta todas as linhas do arquivo e subtraímos o arquivo sem as linhas vazias finais.
E como conseguir isso? $(grep -B42 . "$1"
iria grep todas as linhas não vazias e 42 linhas antes delas, então imprimiria tudo até a última linha não vazia, desde que não houvesse mais de 42 linhas vazias consecutivas antes de uma linha não vazia. Para evitar esse limite, tomo $(grep -cv . "$1")
como parâmetro da -B
opção, que é o número total de linhas vazias, portanto sempre grande o suficiente. Dessa forma, eliminei as linhas vazias finais e posso usá-las |grep -c ".*"
para contar as linhas.
Brilhante, não é? (-;