Substitua \ n por uma nova linha no sed portably

23

Estou tão confuso com a infinidade de opções do GNU sed, POSIX sede BSD sed. Como substituo literal \npelo caractere de nova linha usando esses três sedtipos?

Avinash Raj
fonte
Eles têm muitas coisas diferentes, que parte você quer saber?
precisa saber é
@ Gnouc acho que agora está claro.
Avinash Raj
1
Você deu uma olhada nesta pergunta ?
groxxda
2
O que você quer que aconteça na entrada como foo\\nbarou foo\\\nbar?
Gilles 'SO- stop be evil'
simples, foo \\ na próxima linha seria bar.
precisa

Respostas:

30
sed 's/\\n/\
/g'

Observe a barra invertida imediatamente antes de retornar na string de substituição.

unxnut
fonte
isso funciona para todos os tipos de sed?
Avinash Raj
Eu acredito que deveria; Eu testei apenas no Linux usando a versão gnu.
unxnut
11
@AvinashRaj. Esse é o POSIX e funcionou com o sedcomando original no Unix v7 em 1979. O único lugar em que isso pode não funcionar seria implementações despojadas que não sejam POSIX, sedcomo algumas baseadas no busybox despojado. Isso não funcionará no csh, mas é um problema do csh.
Stéphane Chazelas
Como \\né usado na parte de pesquisa, por que não usar \nna substituição? o primeiro parece implicar que o último existe. ie Por que não isso$ echo '1\n2'|sed 's/\\n/\n/g'
Nesse caso, \né um literal, implicando que ele aparece como os dois caracteres: abackslash seguido por ne não como um único caractere de nova linha. Assim, duas barras para fazer a barra invertida um literal e, em seguida,n
unxnut
9

Como você já tem sua sedresposta portátil , mencionarei que sedraramente é a melhor ferramenta se você precisar manipular novas linhas. O Perl é quase tão portátil quanto sed, é instalado por padrão na maioria dos sistemas * nix e pode lidar com isso com muita facilidade:

printf '%s\n' 'aa\nbb' | perl -pe 's/\\n/\n/g'

Outra opção muito portátil é awk:

printf '%s\n' 'aa\nbb' | awk  '{gsub("\\\\n","\n")};1'

No Solaris, lembre-se de usar o awk padrão em / usr / xpg4 / bin, o do / bin é histórico e não deve ser usado para novos scripts.

terdon
fonte
Eu diria que awktem problemas de portabilidade semelhantes (É o meu awkvelho liso awk, nawkou gawk?). Na verdade, a versão nas minhas caixas Solaris não existe gsub(). Meu voto aqui é para Perl ( perl -nlawe '...'aproxima o comportamento automático de awk).
ArielCo
2
@arielCo: Para awkportabilidade, awkuse uma versão compatível com POSIX e use apenas esses recursos, e você deve estar bem. No Solaris, você encontrará um como /usr/xpg4/bin/awk.
Scrutinizer
@terdon, que tal isso echo "aa\nbb" | awk '{gsub(/\\n/,"\n");}1;'?
Avinash Raj
@arielCo, na verdade, o awk é mais portátil que o perl. Minha segunda abordagem awk, que não usa, gsub()deve funcionar em quase todos os lugares. Até o busybox tem um awk.
terdon
1
gsub () é POSIX (gsub foi adicionado no SVR3.1, POSIX awk é baseado no SVR4 com algumas adições, consulte o manual do gawk para obter mais informações), gensub () é a extensão GNU. O awk original ainda encontrado como / bin / awk no Solaris, não suportava o suporte gsub (), mas também não suportava um FS com vários caracteres.
Stéphane Chazelas
1

Se o espaço Hantigo estiver vazio, você também poderá:

sed '/\\n/G;s/\\n\(.*\)\(.\)/\2\1/;P;D'

... mas a resposta da uxnut já é mais rápida e mais simples, para que você possa tomá-la como quiser.

Outra possibilidade estranha:

INPUT | sed -n l | while read v ; do printf "${v%?}" ; done

Mas cuidado, ^ que traduz todas as \escapes de barra invertida padrão do estilo C - como \bespaço de trabalho e \return e \00octais e o que você quiser.

mikeserv
fonte
0

Com gnu sedo seguinte também funciona:

gsed -n -e 'H;${x;s/\\n/\n/g;p;}'
Dirk Hoffmann
fonte
-2

Você precisa de uma solução no sed, e isso já é fornecido abaixo. Mas eu queria acrescentar outra possibilidade de que o IMHO seja mais fácil e rápido,

tr -d "\n"
jpmuc
fonte
1
o que isso faz? excluir todas as novas linhas da entrada?
mikeserv
Sim, isso é exatamente o que ele faz
jpmuc
5
mas por que? o que isso tem a ver com a questão?
mikeserv
1
Isso apenas remove "\ n" quando a pergunta está perguntando como substituir a string "\ n" por novas linhas reais.
Spuder