ecoa um arquivo como uma única linha com \ n's

3

Eu tenho um arquivo de texto de várias linhas que desejo ecoar como um arquivo de linha única, em que as novas linhas são mostradas como \ n.

Qualquer ponteiro seria ótimo.

    
por Louise McMahon 26.07.2017 / 11:38

4 respostas

2

A solução que usei foi

< file.txt sed '$!G' | paste -sd '\n' -
  • sed '$!G' acrescenta uma linha vazia a cada linha de entrada, exceto a última ( $ ).
  • paste -sd '\n' cola as linhas resultantes alternadamente com barra invertida e n . E adiciona uma nova linha no final para resultar em saída de texto válida.
por 26.07.2017 / 14:25
7

Usando a marreta Perl:

$ perl -pe 's/\n/\n/' < file.txt ; echo

O echo está lá para imprimir uma nova linha no final, para o caso de ser desejado para fins de exibição. Isso muda o NL na última linha para \n também.

Ou uma solução bastante direta em apenas Bash, supondo que o arquivo não contenha nenhum byte NUL incorporado. Embora note que isso carrega todo o arquivo na memória:

$ IFS= read -r -d '' text < file.txt; printf '%s\n' "${text//$'\n'/\n}"
    
por 26.07.2017 / 13:26
5

Cuidado com alguns casos especiais que você pode precisar considerar aqui. Vamos pegar como exemplo 4 arquivos:

  • file1 um arquivo vazio
  • file2 um arquivo com um único caractere newline (␤) (uma linha vazia)
  • file3 um arquivo de texto adequado como:

    foo␤
    bar␤
    
  • file4 um arquivo com a última linha não delimitada:

    foo␤
    bar
    

Se você quiser:

  • file1 : vazio
  • file2 : \n␤
  • file3 : foo\nbar\n␤
  • file4 : foo\nbar␤

(por exemplo, para que você possa reconstruir o arquivo passando a saída para printf %b ).

Então, você poderia fazer:

perl -pe 's/\n/\n/; END{print "\n" if $.}' < file

Ou com o GNU awk :

gawk '{printf "%s", $0 (RT ? "\n" : "")}
      END{if (NR) print ""}' < file

Você pode se adaptar se quiser ignorar o delimitador da última linha, se houver, ou não quiser a nova linha à direita, mas então você pode querer testar nesses 4 casos diferentes que ela faz o que você quer como você provavelmente vai achar que você precisa ter tratamentos especiais para alguns deles.

Por exemplo, o seu

< file sed '$!G' | paste -sd '\n' -

a solução para ignorar o delimitador da última linha produz uma linha vazia para file1 e file2 (e para texto não delimitado corretamente ( file4 ) pode não funcionar corretamente com todos os sed / paste implementations como aquelas destinadas a lidar com texto válido).

perl -pe 's/\n?$/eof ? "\n" : "\n"/e' < file

pode ser mais portável e talvez um pouco melhor para file1 e file2 , o que deixaria inalterado.

    
por 26.07.2017 / 14:04
4

tr sozinho não pode fazer isso, pois você precisa substituir um caractere por dois caracteres. sed sozinho não pode fazer isso facilmente, pois gera uma nova linha no final de tudo que é impresso. Mas você pode fazer isso combinando os dois: adicione \n no final de cada linha e, em seguida, remova as quebras de linha.

sed 's/$/\n/' | tr -d '\n'

Isso produz um arquivo que termina com \n e nenhuma quebra de linha. Se você quiser uma nova linha no final, faça o seguinte:

{ sed 's/$/\n/' | tr -d '\n'; echo; }

(Observe que isso transforma um arquivo vazio em um arquivo com uma única linha vazia.) Se você não quiser o último \n , sed-lo:

sed 's/$/\n/' | tr -d '\n' | sed 's/\n$//'
    
por 26.07.2017 / 17:04

Tags