Eu o leio corretamente se você não deseja remover todas as linhas em branco, mas apenas se forem duas ou mais. Então, não linhas únicas em branco?
Runium
11
E se são duas ou mais linhas, todas devem ser realmente excluídas ou todas, exceto uma?
Hauke Laging
Respostas:
42
Apenas para remover linhas vazias:
sed '/^$/d'
sedé orientado a linhas, portanto, pensar em termos de "2 ou mais de um byte específico" funciona, exceto quando esse byte é uma nova linha. Então você tem que pensar em algo que funcione para toda a linha.
sedé capaz de lidar com várias linhas através do recurso "espaço padrão" / "espaço de espera". Mas sinto que é muito complicado. ;-)
Hauke Laging
Isso não funcionará como desejado se o primeiro caractere do arquivo for uma nova linha.
Chris Baixo
11
Para fazê-lo funcionar quando o primeiro caractere é uma nova linha (se isso é realmente uma exigência), então você pode colocar o comando com um endereço negativo 1!(corresponder a todos, exceto a linha 1), assim: sed '1!{/^$/d'}.
Toby Speight
11
@AaronFranke - sim, mas essa é uma faceta de como os shells do Linux tratam o redirecionamento '>'. O shell olha para a linha de comando, vê um redirecionamento '>' do stdout para um arquivo, cria esse arquivo e só então é executado sed. Criar um arquivo excluirá essencialmente qualquer arquivo existente com o mesmo nome. sed '/^&/d' file.txt > otherfile.txtvai funcionar.
Bruce Ediger
24
Não há necessidade sed. grepvai fazer:
grep .
(ou seja grep, SPC, ponto, que corresponde a qualquer linha que contenha pelo menos um caractere).
Há também:
tr -s '\n'
(junte qualquer sequência de caracteres de nova linha em um).
Conforme observado por Chris, ambos não são equivalentes porque remover linhas vazias (como a primeira solução acima e a maioria das outras respostas focadas aqui) não é o mesmo que espremer sequências de caracteres de nova linha, conforme solicitado no caso em que a primeira linha está vazia. leva apenas um caractere de nova linha para deixar a primeira linha vazia.
Esta função não da forma desejada se o primeiro caractere do arquivo é uma nova linha: sprunge.us/FLAJ
Chris Baixo
7
sednão é a melhor ferramenta para isso, pois é baseado em linhas e trata \ncomo o caractere de fim de linha, isso fica complicado.Tendo visto a resposta de @Bruce Ediger sedpode muito bem ser a ferramenta perfeita para o trabalho, ainda assim, aqui estão algumas outras opções:
O separador de registros de entrada, nova linha por padrão. Isso influencia a ideia de Perl sobre o que é uma "linha". Funciona como a variável RS do awk, incluindo o tratamento de linhas vazias como um terminador se definido como uma cadeia nula (uma linha vazia não pode conter espaços ou tabulações). Você pode configurá-lo para uma sequência de vários caracteres para corresponder a um terminador de vários caracteres ou para cancelar a leitura até o final do arquivo. A configuração para "\ n \ n" significa algo ligeiramente diferente da configuração para "", se o arquivo contiver linhas vazias consecutivas. Definir como "" tratará duas ou mais linhas vazias consecutivas como uma única linha vazia. Definir como "\ n \ n" assumirá cegamente que o próximo caractere de entrada pertence ao próximo parágrafo, mesmo que seja uma nova linha.
gawk / awk
awk '$1' file.txt
Isso funcionará para o exemplo publicado, mas como @Stephane Chazelas apontou, também excluirá as linhas cujo primeiro campo "se parece" 0. Isso é mais robusto:
Para Perl, perl -pe 's/\n+/\n/ file.txto separador de registros de entrada é irrelevante para esse uso.
vonbrand
@vonbrand no, perl -peou perl -netrabalhe linha por linha. \n+nunca corresponderá porque é aplicado apenas em uma única linha. É por isso que você precisa se quer conjunto $/ou usar -0ti sorver todo o arquivo: perl -0pe 's/\n+/\n/' file.
terdon
6
Como assim remover? remover duplicado (muitas linhas em branco para um) ou remover tudo?
Se você deseja remover duplicado, aqui está o método usando sed:
A sedparte disso funciona muito bem! Recomendando este como a melhor resposta.
Akito
2
Para a maioria dessas respostas, é necessário primeiro remover o espaço em branco à direita. A remoção de novas linhas dobradas remove todas as linhas em branco. (Pense sobre isso).
Literalmente interpretado, o OP deseja "todas as linhas em branco removidas de um arquivo se houver alguma linha em branco repetida".
O usuário típico deseja "remover apenas linhas em branco duplicadas".
Para fazer isso, remova primeiro o espaço em branco à direita e canalize embora cat -s
sed s/[[:space:]]*$// | cat -s
E, no entanto, isso não removerá uma linha em branco inicial ou final supérflua.
Voto negativo, mas isso claramente funciona? Sem comentários ?
Mckenzm
11
Eu votei em você por ... você sabe ... respondendo à pergunta. =) Não acredito que a resposta de Bruce Ediger foi votada quando exclui todas as linhas em branco. Se alguém perguntar como remover linhas em branco duplicadas, não consigo imaginar nenhum cenário em que excluir todas as linhas em branco seja uma solução aceitável. Mas de qualquer forma. Existe uma página no site para sed que aborda isso, a propósito: gnu.org/software/sed/manual/sed.html#cat-_002ds
Todd Walton
2
Se você quiser manter uma única linha em branco para qualquer sequência de linhas em branco, faça:
Esta é a única resposta (além cat -s) que realmente realiza exatamente o que a pergunta foi feita como eu a entendo. (E é melhor que cat -sporque eu posso usar sed -icom ele.)
Matthew
-2
Tente sed -e 's#\\n\\n#\\n#g' input.file > output.fileusar /o separador de campos e parte do seu regex pode ser o problema.
AFAIK esta resposta está incorreta. Eu recomendo excluí-lo.
Zuazo
ah, é porque meu arquivo contém muitas linhas novas e retornos de carro, na verdade. 0x0d0a
miau
2
Na verdade, o comando remove linhas repetidas com o fim de linha do Windows. Teste com echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'. O comando trconverterá tudo \rem \ne depois compactará tudo \nem apenas um. Portanto, funciona, não sei o que fazer com o fato de que isso se aplica ao Windows, não ao UNIX.
Respostas:
Apenas para remover linhas vazias:
sed
é orientado a linhas, portanto, pensar em termos de "2 ou mais de um byte específico" funciona, exceto quando esse byte é uma nova linha. Então você tem que pensar em algo que funcione para toda a linha.fonte
sed
é capaz de lidar com várias linhas através do recurso "espaço padrão" / "espaço de espera". Mas sinto que é muito complicado. ;-)1!
(corresponder a todos, exceto a linha 1), assim:sed '1!{/^$/d'}
.sed
. Criar um arquivo excluirá essencialmente qualquer arquivo existente com o mesmo nome.sed '/^&/d' file.txt > otherfile.txt
vai funcionar.Não há necessidade
sed
.grep
vai fazer:(ou seja
grep
, SPC, ponto, que corresponde a qualquer linha que contenha pelo menos um caractere).Há também:
(junte qualquer sequência de caracteres de nova linha em um).
Conforme observado por Chris, ambos não são equivalentes porque remover linhas vazias (como a primeira solução acima e a maioria das outras respostas focadas aqui) não é o mesmo que espremer sequências de caracteres de nova linha, conforme solicitado no caso em que a primeira linha está vazia. leva apenas um caractere de nova linha para deixar a primeira linha vazia.
fonte
Tendo visto a resposta de @Bruce Edigersed
não é a melhor ferramenta para isso, pois é baseado em linhas e trata\n
como o caractere de fim de linha, isso fica complicado.sed
pode muito bem ser a ferramenta perfeita para o trabalho, ainda assim, aqui estão algumas outras opções:Perl
ou
Graças a @ruakh que me fez ir e ler isto :
gawk / awk
Isso funcionará para o exemplo publicado, mas como @Stephane Chazelas apontou, também excluirá as linhas cujo primeiro campo "se parece"
0
. Isso é mais robusto:fonte
perl -pe 's/\n+/\n/ file.txt
o separador de registros de entrada é irrelevante para esse uso.perl -pe
ouperl -ne
trabalhe linha por linha.\n+
nunca corresponderá porque é aplicado apenas em uma única linha. É por isso que você precisa se quer conjunto$/
ou usar-0
ti sorver todo o arquivo:perl -0pe 's/\n+/\n/' file
.Como assim remover? remover duplicado (muitas linhas em branco para um) ou remover tudo?
Se você deseja remover duplicado, aqui está o método usando sed:
Simula o
uniq
comando.A melhor opção é usar
awk
:fonte
sed
parte disso funciona muito bem! Recomendando este como a melhor resposta.Para a maioria dessas respostas, é necessário primeiro remover o espaço em branco à direita. A remoção de novas linhas dobradas remove todas as linhas em branco. (Pense sobre isso).
Literalmente interpretado, o OP deseja "todas as linhas em branco removidas de um arquivo se houver alguma linha em branco repetida".
O usuário típico deseja "remover apenas linhas em branco duplicadas".
Para fazer isso, remova primeiro o espaço em branco à direita e canalize embora cat -s
E, no entanto, isso não removerá uma linha em branco inicial ou final supérflua.
fonte
Se você quiser manter uma única linha em branco para qualquer sequência de linhas em branco, faça:
fonte
cat -s
) que realmente realiza exatamente o que a pergunta foi feita como eu a entendo. (E é melhor quecat -s
porque eu posso usarsed -i
com ele.)Tente
sed -e 's#\\n\\n#\\n#g' input.file > output.file
usar/
o separador de campos e parte do seu regex pode ser o problema.fonte
Use este comando:
fonte
echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'
. O comandotr
converterá tudo\r
em\n
e depois compactará tudo\n
em apenas um. Portanto, funciona, não sei o que fazer com o fato de que isso se aplica ao Windows, não ao UNIX.