Pode sed substituir novos caracteres de linha?

29

Existe um problema com sed e novo caractere de linha?
Eu tenho um arquivo test.txt com o seguinte conteúdo

aaaaa  
bbbbb  
ccccc  
ddddd  

O seguinte não funciona:
sed -r -i 's/\n/,/g' test.txt

Eu sei que posso usar tr para isso, mas minha pergunta é por que não parece possível com o sed.

Se este for um efeito colateral do processamento do arquivo linha por linha, eu estaria interessado em saber por que isso acontece. Eu acho que grep remove novas linhas. O sed faz o mesmo?

    
por Jim 12.02.2014 / 21:08

7 respostas

37

Com GNU sed e desde que POSIXLY_CORRECT não esteja no ambiente (para entrada de linha única):

sed -i ':a;N;$!ba;s/\n/,/g' test.txt

De link :

  1. crie um marcador por meio de :a
  2. acrescente a linha atual e a próxima ao espaço de padrão via N
  3. se estivermos antes da última linha, ramificar para o rótulo criado $!ba ( $! significa não fazer isso na última linha (como deve haver uma nova linha final)).
  4. finalmente a substituição substitui cada nova linha por uma vírgula no espaço padrão (que é o arquivo inteiro).
por 12.02.2014 / 21:26
6

No site da Oracle:

The sed utility works by sequentially reading a file, line by line, into memory. It then performs all actions specified for the line and places the line back in memory to dump to the terminal with the requested changes made. After all actions have taken place to this one line, it reads the next line of the file and repeats the process until it is finished with the file.

Basicamente, isso significa que, como o sed está lendo linha por linha, o caractere de nova linha não é correspondido.

A solução do link é:

sed ':a;N;$!ba;s/\n/ /g'

Uma explicação sobre como isso funciona é fornecida nessa página.

    
por 12.02.2014 / 21:30
5

Isso funciona:

sed -z 's/\n/,/g' 

-z está incluído desde 4.2.2

    
por 08.08.2017 / 18:59
3

sed sempre remove a linha de frente \n ewline antes de preencher o espaço de padrão e, em seguida, anexa uma antes de escrever os resultados de seu script. Um \n ewline pode ser obtido no padrão de espaço por vários meios - mas nunca se não for o resultado de uma edição. Isso é importante - \n ewlines no espaço de padrão de sed sempre refletem uma alteração e nunca ocorrem no fluxo de entrada. \n ewlines são o único delimitador em que sed der pode contar com entradas desconhecidas.

Se você quiser substituir todos os \n ewlines por vírgulas e seu arquivo não for muito grande, faça o seguinte:

sed 'H;1h;$!d;x;y/\n/,/'

Isso anexa todas as linhas de entrada ao h old space - exceto o primeiro, que em vez disso substitui h old space - seguindo um caractere \n ewline. Em seguida, d elimina cada linha, e não a $! da última saída. Na última linha, H old e espaços padrão são e x alterados e todos os caracteres \n ewline são y/// traduzidos para vírgulas.

Para arquivos grandes, esse tipo de coisa pode causar problemas - o buffer de sed nos limites da linha, que pode ser facilmente sobrecarregado com ações desse tipo.

    
por 24.11.2014 / 01:14
0

Como alternativa, você pode usar uma sintaxe um pouco mais simples:

sed ':a;N;s/\n/,/g;ba'

... apenas mudando a ordem das seqüências.

    
por 22.11.2014 / 13:57
0

Existe uma mágica muito sed aqui. E alguns bons pontos levantados sobre estouro de espaço de padrão. Eu amo usar sed mesmo quando não é a maneira mais simples, porque é tão compacto e poderoso. No entanto, tem suas limitações e, para grandes quantidades de dados, o espaço de padrões teria que ser muito criativo.

GNU diz isso:

For those who want to write portable sed scripts, be aware that some implementations have been known to limit line lengths (for the pattern and hold spaces) to be no more than 4000 bytes. The posix standard specifies that conforming sed implementations shall support at least 8192 byte line lengths. GNU sed has no built-in limit on line length; as long as it can malloc() more (virtual) memory, you can feed or construct lines as long as you like.
However, recursion is used to handle subpatterns and indefinite repetition. This means that the available stack space may limit the size of the buffer that can be processed by certain patterns.

Eu não tenho muito a acrescentar, mas gostaria de lhe indicar o meu guia para sed . É excelente. link

e aqui está a minha solução:

for i in $(cat test.txt); do echo -n $i','; done; echo '' >> somewhere

funciona bem

    
por 12.02.2016 / 15:44
-1

Digamos que você queira substituir as novas linhas por \n . Eu queria fazer isso, então aqui está o que eu fiz:

(echo foo; echo bar; echo baz) | sed -r '$!s/$/\n/' | tr -d '\n' 
# Output: foo\nbar\nbaz

Veja o que ele faz: para todas as linhas exceto a última , anexe \n . Em seguida, exclua novas linhas com tr .

    
por 12.02.2016 / 11:32

Tags