Remplacer \ n par une nouvelle ligne dans sed portablement

23

Je suis tellement confus avec GNU sed, POSIX sedet sedla myriade d'options de BSD . Comment remplacer le littéral \npar le caractère de nouvelle ligne en utilisant ces trois sedtypes?

Avinash Raj
la source
Ils ont beaucoup de choses différentes, quelle partie voulez-vous savoir?
cuonglm
@Gnouc je pense que maintenant c'est clair.
Avinash Raj
1
Avez-vous regardé cette question ?
groxxda
2
Que voulez-vous qu'il se passe sur une entrée comme foo\\nbarou foo\\\nbar?
Gilles 'SO- arrête d'être méchant'
simple, foo \\ dans la ligne suivante, ce serait bar.
Avinash Raj

Réponses:

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

Remarquez la barre oblique inverse juste avant d'appuyer sur return dans la chaîne de remplacement.

unnut
la source
Est-ce que cela fonctionne pour toutes sortes de sed?
Avinash Raj
Je pense que oui; J'ai testé uniquement sur Linux en utilisant la version gnu.
unxnut
11
@AvinashRaj. C'est POSIX et a travaillé avec la sedcommande d' origine dans Unix v7 en 1979. Le seul endroit où cela pourrait ne pas fonctionner serait des implémentations non POSIX allégées sedcomme certaines implémentées allégées basées sur la boîte occupée. Cela ne fonctionnera pas dans csh mais c'est un problème csh.
Stéphane Chazelas
Puisque \\nest utilisé dans la partie recherche, pourquoi ne pas l'utiliser \ndans le remplacement? le premier semble impliquer que le second existe. c'est à dire. pourquoi pas$ echo '1\n2'|sed 's/\\n/\n/g'
Dans ce cas, \nest un littéral, ce qui implique qu'il apparaît comme les deux caractères: abackslash suivi de n, et non comme un seul caractère de nouvelle ligne. Par conséquent, deux barres obliques inverses pour faire de la barre oblique inverse un littéral, puisn
unxnut
9

Puisque vous avez déjà votre sedréponse portable , je mentionnerai simplement que sedc'est rarement le meilleur outil si vous devez en quelque sorte manipuler des nouvelles lignes. Perl est presque aussi portable que sed, est installé par défaut sur la plupart des systèmes * nix et peut gérer cela très facilement:

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

Un autre choix très portable est awk:

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

Sur Solaris, n'oubliez pas d'utiliser le awk standard dans / usr / xpg4 / bin, celui dans / bin est un historique et ne doit pas être utilisé pour les nouveaux scripts.

terdon
la source
Je dirais que awka des problèmes de portabilité similaires (est ma awkplaine vieux awk, nawkou gawk?). En fait, la version de mes boîtiers Solaris manque gsub(). Mon vote ici est pour Perl (se perl -nlawe '...'rapproche du comportement automatique de awk).
arielCo
2
@arielCo: Pour la awkportabilité, restez avec une version awkcompatible POSIX et n'utilisez que ces fonctionnalités et tout devrait bien se passer. Sur Solaris, vous en trouverez un en tant que /usr/xpg4/bin/awk.
Scrutinizer
@terdon qu'en est-il echo "aa\nbb" | awk '{gsub(/\\n/,"\n");}1;'?
Avinash Raj
@arielCo en fait, awk est plus portable que perl. Ma deuxième approche awk qui n'utilise pas gsub()devrait fonctionner à peu près partout. Même busybox a un awk.
terdon
1
gsub () est POSIX (gsub, a été ajouté dans SVR3.1, POSIX awk est basé sur SVR4 avec quelques ajouts voir le manuel de gawk pour plus d'informations), gensub () est l'extension GNU. L'awk d'origine toujours trouvé sous / bin / awk sur Solaris, ne supportait pas non plus la prise en charge de gsub (), mais ne supportait pas non plus un FS à plusieurs caractères.
Stéphane Chazelas
1

Si Holdspace est vide, vous pouvez également faire:

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

... mais la réponse de uxnut est déjà à la fois plus rapide et plus simple, vous pouvez donc la prendre comme bon vous semble .

Une autre possibilité étrangère:

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

Mais attention, ^ qui traduit toutes les \échappements antislash de style C standard - comme \backspace et \return et \00octals et whathaveyou.

mikeserv
la source
0

Avec gnu sedles éléments suivants fonctionne également:

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

Vous avez besoin d'une solution dans sed, qui est déjà donnée ci-dessous. Mais je voulais ajouter une autre possibilité que IMHO est juste plus facile et plus rapide,

tr -d "\n"
jpmuc
la source
1
qu'est-ce que cela fait? supprimer toutes les nouvelles lignes de l'entrée?
mikeserv
Oui, c'est exactement ce qu'il fait
jpmuc
5
mais pourquoi? qu'est-ce que cela a à voir avec la question?
mikeserv
1
Cela supprime simplement "\ n" lorsque la question demande comment remplacer la chaîne "\ n" par des sauts de ligne réels.
spuder