web-dev-qa-db-fra.com

Nouvelles lignes dans sed sur Mac OS X

Je trouve que \n ne fonctionne pas dans sed sous Mac OS X. Spécifiquement, disons que je veux séparer les mots séparés par un seul espace en lignes:

# input
foo bar

J'utilise,

echo "foo bar" | sed 's/ /\n/'

Mais le résultat est stupide, le \n n'est pas échappé!

foonbar

Après avoir consulté Google, j'ai trouvé une solution de contournement :

echo 'foo bar' | sed -e 's/ /\'$'\n/g'

Après avoir lu l'article, je ne comprends toujours pas ce que signifie \'$'\n/g'. Quelqu'un peut-il me l'expliquer ou s'il existe un autre moyen de le faire? Merci!

37
Ivan Z. G. Xiao

Vous pouvez brew install gnu-sed et remplacer les appels à sed par gsed.

Si vous ne voulez pas ajouter le "g" à sed, vous pouvez brew install gnu-sed --with-default-names et simplement appeler sed.

(Edit: drapeau de brassage mis à jour, pointe de chapeau à Clément.)

24
Ahmed Fasih

Ceux-ci fonctionneraient également:

echo 'foo bar' | sed 's/ /\
/g'

echo 'foo bar' | sed $'s/ /\\\n/g'

lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"

Sed d'OS X n'interprète pas \n dans le modèle de remplacement, mais vous pouvez utiliser un saut de ligne littéral précédé d'un caractère de continuation de ligne. Le shell remplace $'\n' par un saut de ligne littéral avant l'exécution de la commande sed.

20
Lri

La solution de contournement que vous avez trouvée transmet une chaîne d'argument unique à sed -e.

Cet argument finit par être une chaîne au format habituel sed s/ / /g.

Cette chaîne est créée en deux parties, l'une après l'autre.

La première partie est citée sous la forme '...'.

La deuxième partie est citée sous la forme $'...'.

La partie 's/ /\' supprime les guillemets simples, mais passe ensuite à sed, telle qu'elle apparaît sur la ligne de commande. C'est-à-dire que la barre oblique inverse n'est pas mangée par bash, elle est transmise à sed.

La partie $'\n/g' obtient le signe dollar et les guillemets supprimés, et le \n est converti en caractère de nouvelle ligne.

Tous ensemble, l'argument devient

s// \newline/g

[C'était amusant. Il a fallu du temps pour le déballer. +1 pour une question intéressante.]

10
Spiff

L'expression $'...' est une bash- ism qui produit ... avec les séquences d'échappement standard développées. Si \' signifie simplement une barre oblique inverse suivie de la fin de la section citée, la chaîne résultante est s/ /\. (Oui, vous pouvez basculer entre guillemets au milieu d'une chaîne; cela ne termine pas la chaîne.)

POSIX standard sed accepte uniquement \n dans le cadre d'un modèle de recherche. OS X utilise FreeBSD sed, qui est strictement conforme à POSIX; Comme d’habitude, GNU ajoute des éléments supplémentaires, puis les utilisateurs de Linux pensent tous que est une sorte de "standard" (peut-être que je serais plus impressionné si d'entre eux avaient un processus de normes).

6
geekosaur

Il est très facile de voir ce qui se passe. Faites simplement écho à la corde!

echo 's/$/\'$'\n/g'

résulte en

s/$/\
/g

ce qui équivaut à s/$/\newline/g

Si vous ne disposiez pas du \ supplémentaire avant le newline, le shell interpréterait le newline comme la fin de la commande prématurément.

1
wisbucky