Ich finde, dass \n
das in sed unter Mac OS X nicht funktioniert. Sagen wir, ich möchte die durch ein einzelnes Leerzeichen getrennten Wörter in Zeilen aufteilen:
# input
foo bar
Ich benutze,
echo "foo bar" | sed 's/ /\n/'
Aber das Ergebnis ist doof, dem \n
ist nicht entgangen!
foonbar
Nachdem ich mich bei Google erkundigt habe, habe ich eine Problemumgehung gefunden :
echo 'foo bar' | sed -e 's/ /\'$'\n/g'
Nach dem Lesen des Artikels kann ich immer noch nicht verstehen, was es \'$'\n/g'
bedeutet. Kann es mir jemand erklären, oder gibt es eine andere Möglichkeit? Vielen Dank!
echo "foo bar" | tr ' ' '\n'
\n
.Antworten:
Sie können
brew install gnu-sed
und ersetzen Anrufesed
mitgsed
.Wenn Sie nicht die „g“ voranstellen wollen
sed
, können Siebrew install gnu-sed --with-default-names
und rufen Sie einfachsed
.(Edit: aktualisierte Sudflagge, Hutspitze an Clément.)
quelle
--with-default-names
und nicht--default-names
. Da diese Option bei meiner Installation jedoch nicht funktioniert hat, musste ich einealias gsed=sed
in meine Installation einfügen~/.profile
, damit sie funktioniert.sed
OS X so verhält, und es wird die falsche Annahme getroffen, diegnu-sed
korrekter ist. Seien Sie kein GNU-Süchtiger und halten Sie sich an POSIX-Standards, um Probleme auf lange Sicht zu vermeiden.Diese würden auch funktionieren:
echo 'foo bar' | sed $'s/ /\\\n/g'
lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"
Sed von OS X wird
\n
im Ersetzungsmuster nicht interpretiert , Sie können jedoch einen Literalzeilenvorschub verwenden, dem ein Zeilenfortsetzungszeichen vorangestellt ist. Die Shell wird$'\n'
durch einen Literalzeilenvorschub ersetzt, bevor der Befehl sed ausgeführt wird.quelle
sed $'s/ /\\\n/g'
arbeitet, aber nichtsed $'s/\\\n/ /g'
?sed
einmal in Linux / Unix verwenden, um Zeilenumbrüche zu entfernen, da diese bei jedem Zeilenumbruch analysiert / aufgeteilt werden. Wenn Sie dies unter Linux / Unix ausführen, wird es auch nichtsecho -e 'foo\nbar' | sed 's/\n//'
Die gefundene Problemumgehung übergibt eine einzelne Argumentzeichenfolge an
sed -e
.Dieses Argument ist eine Zeichenfolge im bekannten sed-
s/ / /g
Format.Diese Zeichenfolge wird in zwei Teilen nacheinander erstellt.
Der erste Teil wird in
'...'
Form zitiert .Der zweite Teil ist formell zitiert
$'...'
.Der
's/ /\'
Teil erhält die einfachen Anführungszeichen entfernt, wird aber ansonsten an sed übergeben, so wie es in der Befehlszeile aussieht. Das heißt, der Backslash wird nicht von Bash gefressen, sondern an Sed weitergereicht.Das
$'\n/g'
Teil erhält das Dollarzeichen und die einfachen Anführungszeichen werden entfernt und\n
in ein Zeilenumbruchzeichen umgewandelt.Alles in allem wird das Argument
s / / \ newline/ g
[Das hat Spaß gemacht. Es dauerte eine Weile, um das auszupacken. +1 für eine interessante Frage.]
quelle
Der Ausdruck
$'...'
ist einbash
-ism, der...
mit den Standard-Escape-Sequenzen expandiert. Th ,\'
bevor er bedeutet nur einen Schrägstrich am Ende des zitierten Abschnitt folgt, ist die resultierende Zeichenfolges/ /\
. (Ja, Sie können die Anführungszeichen in der Mitte einer Zeichenfolge ändern; die Zeichenfolge wird dadurch nicht beendet.)POSIX-Standard
sed
akzeptiert nur\n
als Teil eines Suchmusters. OS X verwendet FreeBSDsed
, das ausschließlich POSIX-konform ist. GNU fügt wie üblich zusätzliches Material hinzu, und dann denken alle Linux-Benutzer, dass dies eine Art "Standard" ist (vielleicht wäre ich mehr beeindruckt, wenn einer von ihnen einen Standardprozess hätte).quelle
$'...'
Teil. Aber ... was ists/ /\
? Was meinst du damitswitch quoting
?'...'
ist eine Art von Shell-Zitaten;$'...'
ist ein anderer. Es gibt auch"..."
und\x
ein einzelnes Zeichen zu zitieren. Sie können diese in einem einzigen Wort kombinieren, was dort gemacht wurde, indem Sie von einer normalen''
Zeichenfolge zu einer$''
Zeichenfolge wechseln, um die Zeichenfolge zu übersetzen\n
. Im Übrigen baut es einsed
Kommando auf (s/text/replacement/flags
). In diesem Fall wird der Befehl mit einem Backslash am Ende gestartet, um die angehängte wörtliche Newline zu schützen$'\n/g'
. Das Ergebnis ist, dass alle (die/g
Flag-) Leerzeichen durch Zeilenumbrüche ersetzt werden.Es ist sehr einfach, visuell zu sehen, was passiert. Einfach die Saite wiedergeben!
Ergebnisse in
das ist äquivalent zu
s/$/\
newline/g
Wenn Sie das Extra
\
vor dem nicht hattennewline
, würde die Shell dasnewline
als das Ende des Befehls vorzeitig interpretieren .quelle