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?
text-processing
grep
wc
Raghunath Choudhary
fonte
fonte
grep
@MichaelJohn vence pela pureza no meu livro.Respostas:
Se as linhas em branco estiverem apenas no final
ou:
fonte
grep -cv . myFile
é outra maneira de escrevê-lo (para jogadores de código). Mas eu encontrei uma solução comgrep
se houver linhas vazias em qualquer lugar do arquivo.grep -cv .
também contaria as linhas que contêm apenas bytes que não formam caracteres válidos.Apenas por diversão, alguns assustadores
sed
:Explicação:
/./
endereça linhas com qualquer caractere; portanto,/./!
endereça linhas não vazias; para aqueles, oH
comando anexa-os ao espaço de espera. Portanto, se para cada linha vazia adicionamos uma linha ao espaço de espera, sempre há mais uma linha que o número de linhas vazias. Nós 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 e movida para o espaço de espera peloh
comando para "redefinir" as linhas coletadas para 1. Quando a próxima linha vazia for anexada, haverá dois novamente, conforme o esperado.$!d
interrompe o script sem saída para todas as linhas, exceto a última, para que outros comandos sejam executados somente após a última linha. Portanto, quaisquer linhas vazias que coletamos no espaço de espera estão no final do arquivo. Boa.//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. Boa.x
as trocas mantêm espaço e espaço padrão, portanto as linhas coletadas estão no espaço padrão agora para serem processadas.s/\n//
.wc -l
.fonte
Mais algumas opções
tac
/ GNUtail -r
:Ou:
Observe que na saída de:
Ou seja, onde há um espaço extra após a última linha completa (que alguns poderiam considerar como uma linha em branco extra, mas pela definição de texto POSIX, não é um texto válido), esses dariam 0.
POSIXly:
mas isso significa ler o arquivo na íntegra (
tail -r
/tac
leria o arquivo para trás a partir do final em arquivos pesquisáveis). Isso dá1
a saída deprintf 'x\n '
.fonte
Como você está realmente pedindo uma
grep
solução, eu adiciono estagrep
usando apenas o GNU (ok, também usando a sintaxe do shell eecho
...):O que estou fazendo aqui?
$(grep -c ".*" "$1")
conta todas as linhas do arquivo e subtraímos o arquivo sem as linhas vazias à direita.E como conseguir isso?
$(grep -B42 . "$1"
grep todas as linhas não vazias e 42 linhas antes delas, para imprimir tudo até a última linha não vazia, desde que não haja mais de 42 linhas vazias consecutivas antes de uma linha não vazia. Para evitar esse limite, tomo$(grep -cv . "$1")
como parâmetro para a-B
opção, que é o número total de linhas vazias, portanto sempre grande o suficiente. Dessa maneira, retirei as linhas vazias à direita e posso usá|grep -c ".*"
-las para contar as linhas.Brilhante, não é? (-;
fonte
tac | grep
para o primeiro sem espaço em branco-m -A 42
e depois para menos um. Não tenho certeza do que é mais eficiente, mas você também pode, emwc -l | cut -d' ' -f1
vez de cumprimentar as linhas em branco?tac
,wc
ecut
, mas aqui tentei me restringirgrep
. Você pode chamar isso de perversidade, eu chamo de esporte. (-;Outra
awk
solução. Essa variação redefine o contadork
sempre que houver uma linha que não esteja em branco. Então, cada linha incrementa o contador. (Então, após a primeira linha de comprimento sem espaço em brancok==0
,.) No final, produzimos o número de linhas que contamos.Prepare o arquivo de dados
Contar as linhas em branco à direita na amostra
Nesta definição, uma linha em branco pode conter espaços ou outros caracteres em branco; ainda está em branco. Se você realmente deseja contar linhas vazias em vez de linhas em branco, mude
NF
para$0 != ""
.fonte
$0 > ""
? Os usosstrcoll()
que seriam menos eficientes do$0 != ""
que os usadosmemcmp()
em muitas implementações (o POSIX exigia que fosse usadostrcoll()
).$0 > ""
diferente$0 != ""
. Eu costumo tratarawk
como um operador "lento" de qualquer maneira (de modo que, se eu souber que tenho um grande conjunto de dados como entrada e o processamento for muito demorado, verei o que posso fazer para reduzir a quantidadeawk
a processar - I usaramgrep | awk
construções nessas situações). No entanto, tendo examinado rapidamente o que presumo ser a definição POSIX, não vejo nenhuma referência a umstrcoll()
ou a outromemcmp()
. o que estou perdendo?strcoll()
== as seqüências de caracteres devem ser comparadas usando a sequência de intercalação específica da localidade . Compare com a edição anterior . Fui eu quem falou disso. Veja também austingroupbugs.net/view.php?id=963a <= b && a >= b
não é necessariamente o mesmo quea == b
. Ai!awk
oubash
(para os seus[[ a < b ]]
operadores) em en_US.UTF-8 localidades em sistemas GNU para instância para①
vs②
, por exemplo (parabash
, nenhum<
,>
,=
retornar verdadeiro para aqueles). Indiscutivelmente é um bug na definição dessas localidades a mais que em bash / awkSolução sólida
awk
+tac
:Amostra
input.txt
:A acção:
!NF
- garante que a linha atual esteja vazia (sem campos)NR==++c
- garantir a ordem consecutiva de linhas em branco. (NR
- número do registro,++c
- contador auxiliar uniformemente aumentado)cnt++
- contador de linhas em brancoA saída:
fonte
IIUC, o seguinte script chamado
count-blank-at-the-end.sh
faria o trabalho:Exemplo de uso:
Eu testei-o em
GNU bash
,Android mksh
e emksh
.fonte
Python
Solução alternativa :Amostra input.txt:
A acção:
A saída:
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile
fonte