61 votes

Newlines dans sed sur Mac OS X

Je trouve que \n ne fonctionne pas dans sed sous Mac OS X. Plus précisément, 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 ne s'échappe pas !

foonbar

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

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

Après avoir lu l'article, je n'arrive toujours pas à comprendre ce que \'$'\n/g' moyens. Quelqu'un peut-il me l'expliquer, ou s'il existe une autre façon de procéder ? Merci !

37voto

Ahmed Fasih Points 839

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


Pour l'utiliser comme sed au lieu de gsed brew, qui imprime utilement les instructions suivantes après l'installation :

GNU "sed" has been installed as "gsed".
If you need to use it as "sed", you can add a "gnubin" directory
to your PATH from your bashrc like:

    PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"

C'est-à-dire, ajoutez la ligne suivante à votre ~/.bashrc ou ~/.zshrc :

export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"

32voto

Dave Points 986

Ceux-ci feraient également l'affaire :

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

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

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

Le 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' avec un saut de ligne littéral avant l'exécution de la commande sed.

12voto

Spiff Points 95683

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

Cet argument finit par être une chaîne dans le format familier sed s/ / /g format.

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

La première partie est citée dans '...' formulaire.

La deuxième partie est citée dans $'...' formulaire.

En 's/ /\' est dépouillé des guillemets simples, mais il est transmis à sed tel qu'il apparaît sur la ligne de commande. C'est-à-dire que la barre oblique inversée n'est pas mangée par bash, elle est passée à sed.

En $'\n/g' le signe dollar et les guillemets simples sont supprimés, et la partie \n est converti en un caractère de nouvelle ligne.

Tout compte fait, l'argument devient

s/ /\ newline /g

[C'était amusant. Ça a pris un moment pour le déballer. +1 pour une question intéressante.]

8voto

geekosaur Points 11085

L'expression $'...' es un bash -isme qui produit ... avec les séquences d'échappement standard étendues. Th \' avant cela signifie simplement une barre oblique inverse suivie de la fin de la section citée, la chaîne résultante est la suivante s/ /\ . (Oui, vous pouvez changer de guillemet au milieu d'une chaîne de caractères ; cela ne met pas fin à la chaîne).

Norme POSIX sed accepte uniquement \n dans le cadre d'un modèle de recherche. OS X utilise le système FreeBSD sed qui est strictement conforme à POSIX ; GNU, comme d'habitude, ajoute des trucs supplémentaires et les utilisateurs de Linux pensent alors tous que que est une sorte de "norme" (je serais peut-être plus impressionné si l'un ou l'autre avait un processus de normalisation).

6voto

wisbucky Points 2298

Il est très facile de voir visuellement ce qui se passe. Il suffit de faire écho à la chaîne de caractères !

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

résulte en

s/$/\
/g

ce qui est équivalent à s/$/\newline/g

Si vous n'aviez pas le supplément \ avant le newline le Shell interprèterait le message newline comme la fin de la commande prématurément.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X