Das Verhalten von Shell-Dienstprogrammen unterscheidet sich geringfügig zwischen Unix-Varianten. Es gibt viele Unix- Varianten mit einer komplexen Geschichte . Es gibt Standardisierungsbemühungen wie den POSIX- Standard, der die Single-UNIX-Spezifikation übersteigt . Die meisten Systeme implementieren heutzutage POSIX: 2001, auch bekannt als Single UNIX Specification Version 3 , mit geringfügigen Abweichungen und vielen Erweiterungen. Die Single Unix-Spezifikation ist kein Tutorial, aber Version 3 ist lesbar, wenn Sie bereits eine Vorstellung davon haben, was ein Befehl tut. Sie können nachlesen, ob es sich bei einer Funktion um eine Standardfunktion oder eine Erweiterung eines bestimmten Systems handelt.
Ein Großteil der Unix-Benutzer verwendet Linux und hat keine andere Variante verwendet. Linux wird mit GNU- Dienstprogrammen geliefert, die häufig viele Erweiterungen des Standards enthalten. Sie werden also eine Menge Code finden, der unter Linux funktioniert, aber nicht auf anderen Unices, da er auf diesen Erweiterungen basiert.
Bezüglich sed konsultieren Sie die sed Single Unix-Spezifikation für das Minimum, das jedes System unterstützen soll, die Manpage auf Ihrem System für das, was Ihre Implementierung unterstützt, und das GNU sed-Handbuch für das, was die meisten Leute da draußen verwenden.
Eine der nicht standardmäßigen Erweiterungen in GNU sed unterstützt mehrere Befehle, die zusammen ausgeführt werden. Dieses GNU sed-Programm druckt beispielsweise alle Zeilen, die ein enthalten a
, ändert sich jedoch b
in c
zuerst:
sed -ne '/a/ {s/b/c/g; p}'
{
und }
sind eigentlich separate Befehle. Um eine vollständige Portabilität zu gewährleisten, müssen Sie sie entweder in separaten Zeilen (in einer Datei) oder in separaten -e
Argumenten (in der Befehlszeile) angeben . Das Fehlen eines Befehlstrennzeichens nach {
und die Verwendung ;
als Befehlstrennzeichen sind häufige Erweiterungen. Das Fehlen eines Befehlstrennzeichens }
ist eine seltenere Erweiterung. Dies ist standardkonform:
sed -n -e '/a/ {' -e 's/b/c/g' -e p -e '}'
Dies ist kein Standard, wird aber allgemein akzeptiert:
sed -ne '/a/ { s/b/c/g; p; }'
Eine weitere nicht standardmäßige, aber weit verbreitete Erweiterung ist die Verwendung von \n
, um eine neue Zeile in einem s
Ersetzungstext zu bezeichnen (die Verwendung in einem regulären Ausdruck ist Standard). Die portable Methode besteht darin, Backslash-Newline in das sed-Skript aufzunehmen. Eine weitere gemeinsame Erweiterung ist \+
, \?
und \|
in einer oder mehrere regexps bedeutet, und höchstens einen Wechsel; Portable Basic Regular Expressions haben keine davon. Beispielsweise ist der erste Befehl eine nicht übertragbare Methode, um zusammenhängende Sequenzen von Leerzeichen durch eine neue Zeile zu ersetzen. Der zweite Befehl ist ein standardkonformes Äquivalent.
sed -e 's/ \+/\n/'
sed -e 's/ */\
/'
sed
selbst ist konform, da es Dinge tut, die der Standard erlaubt (aber nicht erforderlich, nicht spezifiziert). Es gibt Fälle, in denen es nicht konform ist und in denen das AusführenPOSIXLY_CORRECT
in der Umgebung hilfreich sein kann. Wie beis/[\n]//g
diesem muss man den Backlash und dien
Zeichen entfernen, aber stattdessen die Newlines entfernen. Oder das Verhalten desN
Befehls in der letzten Zeile.sed -ne '/a/ { s/b/c/g; p; }'
ist Standard seit der Ausgabe 2016 des Standards. Es war immer tragbar. Siehe austingroupbugs.net/view.php?id=944&nbn=7OS X wird derzeit mit einer FreeBSD-Version ab 2005 ausgeliefert. Die meisten der folgenden Unterschiede gelten auch für andere BSD-Versionen.
Die sed-Verwendungen von OS X
-E
für ERE- und GNU-sed-Verwendungen-r
.-E
ist ein Alias für-r
in GNU sed (hinzugefügt in 4.2, nicht dokumentiert bis 4.3). Neuere Versionen von FreeBSD und NetBSD sed unterstützen sowohl-E
als auch-r
. OpenBSD sed unterstützt nur-E
.-i ''
funktioniert mit OS X's sed aber nicht mit GNU sed.-i
funktioniert mit GNU sed, neueren Versionen von NetBSD, OpenBSDsed
, aber nicht mit OS X sed.-i -e
funktioniert mit beiden, aber im Falle von FreeBSDsed
wird eine Sicherungskopie der Originaldatei mit dem-e
angehängten Dateinamen erstellt (und Sie müssen nicht mehr als einen Ausdruck übergebensed
).GNU sed interpretiert Escape - Sequenzen wie
\t
,\n
,\001
,\x01
,\w
, und\b
. OS X's sed und POSIX sed interpretieren nur\n
(aber nicht im Ersatzteil vons
).GNU sed interpretiert
\|
,\+
und\?
in BRE aber OS X sed und POSIX sed nicht.\(
,\)
,\{
, Und\}
sind POSIX BRE.GNU sed erlaubt das Auslassen von
;
Zeilen oder eine neue Zeile}
, OS X's sed nicht.i
(insert),a
(append) undc
(change) müssen in sed und POSIX sed von einem Backslash und einer Newline gefolgt werden, nicht jedoch in GNU sed. GNU sed eine fehlende Newline nach dem von eingefügten Text fügt hinzui
,a
oderc
aber OS X sed ist nicht der Fall. Zum Beispielsed 1ia
ist eine GNU-Alternative zused $'1i\\\na\n'
.printf a|sed -n p
Fügt beispielsweise eine neue Zeile in OS Xs sed hinzu, jedoch nicht in GNU sed.In OS X werden die Modifikatoren
I
( ohne Berücksichtigung der Groß- und Kleinschreibung) oderM
(mit mehreren Zeilen) nicht unterstützt . Neuere Versionen von FreeBSD sed unterstützenI
.Sed von OS X unterstützt
-s
(--separate
),-u
(--unbuffered
) oder-z
(--null-data
) nicht.Eine BSD-Option, die von GNU sed nicht unterstützt wird
-a
, besteht darin ,w
an eine Datei anzuhängen, anstatt eine Datei abzuschneiden.Beispiele für GNU sed-Befehle, die mit sed von OS X nicht funktionieren:
quelle
-i -e
funktioniert nicht unter OSX. Es wird-e
als Suffix eingefügt.-i
immer ein Suffix benötigt, auch wenn eine leere Zeichenkette. so-i '' -e
sollte funktionieren.-i -e
funktioniert mit beiden." In Ihrer Antwort heißt es, dass es eine plattformübergreifende Lösung gibt. Anscheinend gibt es das nicht.Ich habe festgestellt, dass unter Linux und Mac am besten die gleichen Skripte funktionieren:
quelle
perl
woher das-i
kommt.perl -Tpi -e 's/foo/bar/' -- "$TARGET"