Eu tenho um arquivo .csv (em um mac) que possui várias linhas vazias, por exemplo:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
Que eu quero converter para:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
Eu sei que deve haver uma fila, mas não sei awk ou sed. Algumas dicas muito apreciadas!
shell
text-processing
sed
awk
pitosalas
fonte
fonte
Respostas:
Você pode usar o modo grep
-v
(correspondência invertida) para fazer isso:Observe que esses arquivos precisam ser diferentes, devido ao modo como os redirecionamentos de shell funcionam. O arquivo de saída é aberto (e esvaziado) antes da leitura do arquivo de entrada. Se você tiver moreutils (não por padrão no Mac OS X), poderá usar
sponge
para contornar isso:Mas é claro que você terá mais dificuldade em voltar se algo der errado.
Se você "linhas em branco" realmente pode conter espaços (parece que sim), então você pode usar isso:
Isso ignorará as linhas em branco e as linhas que contêm apenas espaços em branco. É claro que você pode fazer a mesma
sponge
transformação nele.fonte
egrep -v '^[[:space:]]*$'
... nota grep -> egrep e o novo padrão estranhoiconv -f utf16le file.csv | head
ouiconv -f utf16be file.csv | head
A opção mais fácil é justa
grep .
. Aqui, o ponto significa "corresponder a qualquer coisa"; portanto, se a linha estiver vazia, ela não corresponderá. Caso contrário, imprime toda a linha como está.fonte
Para remover linhas vazias, no lugar , com ksh93:
O
<>;
operador de redirecionamento é específico para ksh93 e é o mesmo que o<>
operador padrão , exceto que o ksh trunca o arquivo após o término do comando.sed '/./!d'
é uma maneira complicada de escrevergrep .
, mas infelizmente o GNU grep reclama pelo menos se o seu stdout apontar para o mesmo arquivo que o stdin. Você diria que alguém poderia escrever:Mas, infelizmente, há um bug no ksh93 (pelo menos minha versão (93u +)), pois o arquivo parece estar truncado para um comprimento zero nesse caso.
Parece contornar esse bug, mas agora é muito mais complicado do que o comando sed.
fonte
awk '/./' file 1<>; file
que funcionou. Para mim, isso é ainda mais clara do quesed '/./!d'
Aqui está uma
Perl
linha para isso:EDIT: Código aprimorado com base nos comentários de ruakh abaixo.
fonte
perl -ni -e '/./ and print' yourfile
$
é uma âncora (largura zero), portanto exclui a nova linha. Quanto ao espaço supérfluo, é a razão pela qual eu adicionei o/x
que eu não queriaPerl
tentar interpolação `$ \` para o regex$
, dado que você tem o\n
. (Como alternativa - você não precisa do\n
, dado que possui o\s*
e o$
; mas acho ques/^\s*\n//
deixa mais claro que a nova linha foi removida.) Você também não precisa do/m
; não tem efeito sobre este comando. E uma vez que você se livrar do$
espaço, não precisará dele/x
.\n
próprio pode ser removido; o que você não pode fazer é remover tanto o$
e a\n
. Entãos/^\s*//
, teria o problema que você descreve, mass/^\s*$//
ficaria bem, por causa do\s*
e do$
. (Você vê o que eu quero dizer?)$
pode corresponder antes de uma nova linha (desde que o/m
sinalizador esteja ativado ou a nova linha seja o último caractere da string, ou ambos), mas também pode corresponder ao final da string. Por exemplo,"abc" =~ m/^abc$/
é verdade. No caso de\s*$
, o\s*
é ganancioso o suficiente para consumir a nova linha e, em seguida,$
corresponde ao final da cadeia. (Mas eu acho ques/^\s*\n//
é mais claro, de qualquer maneira, para que a sua resposta é muito bem como é agora.)Com base no esclarecimento nos comentários da sua pergunta, algo como:
pode fazer o que quiser.
Um separador de registros vazio é um caso especial que informa
awk
que os registros devem ser parágrafos (separados por sequências de linhas vazias). Definir o separador de registros de saída como uma sequência vazia também significa que o conteúdo desses parágrafos (sem os separadores) deve ser concatenado.1
é apenas uma condição verdadeira para imprimir todos os registros.No entanto, isso omitiria a nova linha à direita, para que você pudesse:
fonte
Sei que isso seria mais fácil se eu desse o arquivo, mas infelizmente ele continha informações confidenciais que não consegui compartilhar. Enquanto isso, escrevi-me um script em rubi que parecia fazer o truque:
Obrigado a todos por ajudar!
fonte
produz
fonte
Encontrei uma idéia para uma possível solução no stackoverflow .
sed -i ':a;N;$!ba;s/[^"]\n\s*\n/ /g' file.csv
Provavelmente, você deve fazer backup do seu arquivo csv antes de testá-lo, mas pelo menos para o exemplo que você forneceu, ele funciona perfeitamente.
Uma boa explicação sobre o funcionamento interno dessa expressão é oferecida na resposta, apenas a editei para procurar linhas que não terminam com a
"
([^"]\n
).fonte
Se, a partir de sua própria resposta, você deseja remover os caracteres de nova linha contidos nas cadeias citadas, você pode:
Você também pode usar o
-i
sinalizador de perl para editar os arquivos no local .Ou com o GNU awk:
ou:
(se você estiver competindo pelo menor)
Note-se que aqueles assumir que não há são escapou caracteres aspas duplas na entrada.
fonte
Parece que você deseja mais do que remover linhas vazias, mas remova cada sequência de 2 ou mais caracteres de nova linha.
O que você pode fazer com o perl:
Você também pode usar o
-i
sinalizador de perl para editar os arquivos no local .fonte
Existe uma maneira cada vez mais curta de remover linhas vazias em
AWK
:awk 'NF' file
Mas, para obter a saída desejada, tudo o que é necessário é um liner simples:
awk 'NF {printf("%s ", $0); i++;} !(i % 2) {printf("\n");}' file
Explicação
Em
AWK
, uma linha vazia significa que a linha / registro não possui campos, ou seja, aNF
variável (Número de campos) é zero. O liner acima só será executado quandoNF > 0
, imprimindo todas as linhas, exceto as vazias.O
i++
é o contador de linhas não vazias.The
!(i % 2)
é usado para imprimir duas linhas consecutivas não vazias no caminho da saída desejada, ou seja, toda vez que um múltiplo de 2 é encontrado, amodulo
instrução!(i % 2)
gera 1, o que encerra a concatenação de duas linhas não vazias.fonte
Você pode usar o Vim no modo Ex:
v/./
encontre linhas vaziasd
excluirx
salvar e fecharfonte