Exclua linhas vazias usando sed


350

Estou tentando excluir linhas vazias usando sed:

sed '/^$/d'

mas não tenho sorte com isso.

Por exemplo, eu tenho estas linhas:

xxxxxx


yyyyyy


zzzzzz

e eu quero que seja assim:

xxxxxx
yyyyyy
zzzzzz

Qual deve ser o código para isso?


2
o seu comando se parece sed bem, ele deve funcionar
Perreal

O comando acima não funcionaria mesmo se você não tiver um espaço / tab, mas as terminações de linha CR + LF .
devnull

Respostas:


628

Você pode ter espaços ou tabulações na sua linha "vazia". Use as classes POSIX com sedpara remover todas as linhas que contêm apenas espaço em branco:

sed '/^[[:space:]]*$/d'

Uma versão mais curta que usa ERE, por exemplo, com o gnu sed:

sed -r '/^\s*$/d'

(Observe que o sed NÃO suporta PCRE.)


3
@HuStmpHrrr gnu sed não suporta PCRE. é ERE com-r
Kent

8
OS X necessário sed -i "" '/^[[:space:]]*$/d' <filename>,
JWW

O @BernieReiter ^\s*$corresponderá a todas as linhas "vazias". Vazio aqui significa, a linha não contém caracteres ou a linha contém apenas cadeias vazias (por exemplo, espaços). Todas as linhas correspondentes serão removidas pelo sed, com o dcomando
Kent

96

Estou faltando a awksolução:

awk 'NF' file

O que retornaria:

xxxxxx
yyyyyy
zzzzzz

Como é que isso funciona? Como NFsignifica "número de campos", essas linhas vazias têm 0 campos, de modo que o awk avalia 0 como Falso e nenhuma linha é impressa; no entanto, se houver pelo menos um campo, a avaliação será True e awkexecutará sua ação padrão: imprima a linha atual.


11
Whoah. Está funcionando mesmo com a versão de BSD "minimizado" do awk (versão 20121220 (FreeBSD) Thanks :-).
Bernie Reiter

@BernieReiter, de nada :) Sim, isso é uma coisa idiomática muito básica que todas as versões do awk permitem.
fedorqui 'Então pare de prejudicar'

E é muito mais rápido, embora - para um teste rápido e sujo - eu esteja invocando o awk duas vezes: $ time (topic companies <data.tpx | awk 'NF' - | awk -f dialog_menu.awk -) real 0m0.006s user 0m0.000s sys 0m0.008s $ time (topic companies <data.tpx | gsed '/^\s*$/d' | awk -f dialog_menu.awk -) real 0m0.014s user 0m0.002s sys 0m0.006s você saberia uma maneira bacana de incluir isso em um script do awk como, por exemplo, um padrão? awk '/ mypattern / {do stuff ...}' '
Bernie Reiter

@BernieReiter você pode dizer awk 'NF {do stuff...}'.
fedorqui 'Então pare de prejudicar'

11
Observe que isso também ignorará as linhas apenas com espaços em branco.
wisbucky

60

sed '/^$/d'deve ficar bem, você espera modificar o arquivo no lugar? Nesse caso, você deve usar a -ibandeira.

Talvez essas linhas não estejam vazias, portanto, se for esse o caso, observe esta pergunta Remova as linhas vazias dos arquivos txtfiles, remova espaços do início e do fim da linha . Acredito que é isso que você está tentando obter.


sim. Estou modificando um arquivo. * .csv. como o -i deve ser colocado no comando sed?
jonas

2
sed -i '/^$/d'é uma maneira de fazer isso.
Alberto Zaccagni

49

11
Eles são exibidos corretamente em sua ferramenta online, mas não[] devem ser escapados em uma expressão entre colchetes; portanto, o código aqui não está correto ou - deve ser e . \[\[:space:\]\]\[ \t\][[:space:]][ \t]
Benjamin W.

11
@BenjaminW. Obrigado por capturar isso. Aqueles não eram do autor original, mas vieram do Edit 3 quando foi alterado de texto normal para "código", que então "expôs" o escape `\`. Eu os consertei agora.
wisbucky

30

Eu acredito que este é o mais fácil e rápido:

cat file.txt | grep .

Se você precisar ignorar todas as linhas de espaço em branco, tente o seguinte:

cat file.txt | grep '\S'

Exemplo:

s="\
\
a\
 b\
\
Below is TAB:\
    \
Below is space:\
 \
c\
\
"; echo "$s" | grep . | wc -l; echo "$s" | grep '\S' | wc -l

saídas

7
5

5
Não é necessário cat, grepleva arquivos também:grep . file.txt
Ciro Santilli #: 161616

3
Sim, eu sei, mas a pergunta inicial não mencionou se a fonte é um arquivo ou outra coisa; portanto, a solução é o que vem depois de "|" e, antes disso, apenas um exemplo de fonte. Simplesmente para distinguir a solução da fonte de linhas.
Vadim

2
grep '\S'definitivamente não é portátil. Se você tiver grep -P, poderá usar, grep -P '\S'mas também não é suportado em todas as plataformas.
Tripleee

A desvantagem em grep .comparação com as outras soluções é que destacará todo o texto em vermelho. As outras soluções podem preservar as cores originais. Compare unbuffer apt search foo | grep .comunbuffer apt search foo | grep -v ^$
wisbucky

15

Com a ajuda da resposta aceita aqui e a resposta aceita acima, usei:

$ sed 's/^ *//; s/ *$//; /^$/d; /^\s*$/d' file.txt > output.txt

`s/^ *//`  => left trim
`s/ *$//`  => right trim
`/^$/d`    => remove empty line
`/^\s*$/d` => delete lines which may contain white space

Isso cobre todas as bases e funciona perfeitamente para minhas necessidades. Parabéns aos pôsteres originais @Kent e @kev


5

Você pode dizer:

sed -n '/ / p' filename    #there is a space between '//'

.. o que significa print all lines except the empty one(s)e fique quieto
Timo

2

Você pode fazer algo assim usando "grep" também:

egrep -v "^$" file.txt


2

Você provavelmente está vendo um comportamento inesperado porque seu arquivo de texto foi criado no Windows; portanto, a sequência de fim de linha é \r\n. Você pode usar o dos2unix para convertê-lo em um arquivo de texto no estilo UNIX antes de executar o sed ou usar

sed -r "/^\r?$/d"

para remover linhas em branco, independentemente de o retorno de carro estar lá.


Olá, o que a -rbandeira está fazendo e é possível combiná-la -ipara modificar o arquivo diretamente e evitar a impressão na tela. Além disso, eu acho que este comando também funcionaria comosed -r "/^\r$/d"
Alexander Cska

2

Outra opção sem sed, awk, perl, etc

strings $file > $output

strings - imprime as strings de caracteres imprimíveis nos arquivos.


Você quer dizer em stringsvez de string?
Mickael B.

Olá @MickaelB. Você está certo, eu conserto.
user319660

0

Minha bashresposta específica é recomendar o uso do perloperador de substituição com o gsinalizador de padrão global para isso, da seguinte maneira:

$ perl -pe s'/^\n|^[\ ]*\n//g' $file
xxxxxx
yyyyyy
zzzzzz

Esta resposta ilustra como contabilizar se as linhas vazias têm ou não espaços ( [\ ]*), além de usar |para separar vários termos / campos de pesquisa. Testado no macOS High Sierra e CentOS 6/7.

Para sua informação, o código original do OP sed '/^$/d' $filefunciona perfeitamente no bashTerminal no macOS High Sierra e no CentOS 6/7 Linux em um cluster de supercomputação de alto desempenho.


-3

Para mim, o FreeBSD 10.1 com o sed funcionou apenas nesta solução:

sed -e '/^[     ]*$/d' "testfile"

dentro, []há símbolos de espaço e tabulação.

arquivo de teste contém:

fffffff next 1 tabline ffffffffffff

ffffffff next 1 Space line ffffffffffff

ffffffff empty 1 lines ffffffffffff

============ EOF =============
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.