Suche…


Einführung

So zitieren Sie aus der @ @ SnoringFrog-Anfrage zur Erstellung eines Themas:

"Einer der größten Sprüche, die sed verwenden, ist Skripts, die fehlschlagen (oder auf unerwartete Weise erfolgreich sind), weil sie für den einen und nicht für den anderen geschrieben wurden. Ein einfaches Herunterfahren der größeren Unterschiede wäre gut."

Bemerkungen

macOS verwendet die BSD- Version von sed [1] , die sich in vieler Hinsicht von der in Linux- Distributionen enthaltenen GNU- sed Version unterscheidet.

Ihr gemeinsamer Nenner ist die Funktionalität von POSIX verordnet: siehe die POSIX sed spec.

Der tragbarste Ansatz besteht darin , nur POSIX-Funktionen zu verwenden , was jedoch die Funktionalität einschränkt :

  • Insbesondere legt POSIX nur die Unterstützung für reguläre Basisausdrücke fest , für die viele Einschränkungen gelten (z. B. keine Unterstützung für | (Alternative), keine direkte Unterstützung für + und ? ) Und unterschiedliche Fluchtanforderungen.

    • Caveat: GNU sed (ohne -r ), tut Unterstützung \| , \+ und \? , das NICHT POSIX-kompatibel ist; Verwenden Sie --posix zum Deaktivieren (siehe unten).
  • So verwenden Sie nur POSIX-Funktionen :

    • (beide Versionen): Verwenden Sie nur die Optionen -n und -e (verwenden Sie nicht -E oder -r , um die Unterstützung für erweiterte reguläre Ausdrücke zu -E )

    • GNU sed : add Option --posix POSIX-only - Funktionalität zu gewährleisten (Sie brauchen nicht unbedingt das, aber ohne sie könnten Sie versehentlich nicht-POSIX - Funktionen ohne Bemerken am Ende mit; Einschränkung: --posix selbst ist nicht POSIX-konform )

    • Die Verwendung von ausschließlich POSIX-Funktionen bedeutet strengere Formatierungsanforderungen (da auf viele in GNU sed verfügbare Funktionen verzichtet wird):

      • Steuerzeichenfolgen wie \n und \t werden im Allgemeinen NICHT unterstützt.
      • Beschriftungen und Verzweigungsbefehle (z. B. b ) müssen über eine separate Option -e mit einer tatsächlichen Zeilenvorschubzeile oder einer Fortsetzung fortgesetzt werden.
      • Details finden Sie unten.

Beide Versionen implementieren jedoch Erweiterungen des POSIX-Standards:

  • Welche Erweiterungen sie implementieren, unterscheidet sich (GNU sed implementiert mehr).
  • selbst die Erweiterungen, die beide implementieren, unterscheiden sich teilweise in der Syntax .

Wenn Sie BEIDE Plattformen unterstützen müssen (Diskussion der Unterschiede):

  • Inkompatible Funktionen:

    • Die Verwendung der Option -i ohne Argument (direkte Aktualisierung ohne Sicherung) ist nicht kompatibel:

      • BSD sed : MUSS -i ''
      • GNU sed : MUSS nur -i (Äquivalent: -i'' ) verwenden - -i '' funktioniert NICHT.
    • -i sinnvollerweise die Zeilennummerierung pro Eingabedatei in GNU sed und den letzten Versionen von BSD sed (z. B. unter FreeBSD 10), jedoch nicht unter macOS ab 10.12 .
      Beachten Sie, dass, wenn keine -i alle Versionsnummernzeilen kumulativ für die Eingabedateien gelten.

    • Wenn die letzte Eingangsleitung nicht über eine nacheilenden Neuen - Zeile (und wird gedruckt):

      • BSD sed : Hängt bei der Ausgabe immer eine neue Zeile an, auch wenn die Eingabezeile nicht auf einer endet.
      • GNU sed : behält den Status der nachlaufenden Newline-Zeile bei , dh sie hängt eine Newline-Zeile nur an, wenn die Eingabezeile auf einer endete.
  • Gemeinsame Merkmale:

    • Wenn Sie Ihre sed Skripte auf das beschränken, was BSD sed unterstützt, funktionieren sie sed auch in GNU sed - mit der bemerkenswerten Ausnahme, dass plattformspezifische erweiterte Regex-Funktionen mit -E . Natürlich verzichten Sie auch auf Erweiterungen, die für die GNU-Version spezifisch sind. Siehe nächster Abschnitt.

Richtlinien für die plattformübergreifende Unterstützung (OS X / BSD, Linux), die sich an den strengeren Anforderungen der BSD-Version orientieren :

Beachten Sie, dass die Abkürzungen macOS und Linux im Folgenden gelegentlich verwendet werden, um sich auf die BSD- bzw. GNU-Versionen von sed zu beziehen, da sie auf jeder Plattform die Standardversionen sind. Es ist jedoch möglich, GNU sed auf macOS zu installieren, beispielsweise mit Homebrew with brew install gnu-sed .

Anmerkung : Wenn die Flags -r und -E nicht verwendet werden ( erweiterte reguläre Ausdrücke), gelten die folgenden Anweisungen für das Schreiben von POSIX-kompatiblen sed Skripten.

  • Um die POSIX-Konformität zu gewährleisten , müssen Sie sich auf POSIX-BREs ( Basic Regular Expressions) beschränken , die leider, wie der Name schon sagt, recht einfach sind.
    Vorbehalt : Nehmen Sie nicht an, dass \| , \+ und \? werden unterstützt: GNU sed unterstützt sie (sofern nicht --posix verwendet wird), BSD sed jedoch nicht - diese Funktionen sind nicht POSIX-kompatibel.
    Während \+ und \? kann auf POSIX-konforme Weise emuliert werden :
    \{1,\} für \+ ,
    \{0,1\} für \? .
    \| (alternativ) kann leider nicht.

  • Verwenden Sie für leistungsfähigere reguläre Ausdrücke -E (anstelle von -r ), um EREs ( erweiterte reguläre Ausdrücke) zu unterstützen (GNU sed dokumentiert -E , aber es funktioniert dort als Alias ​​von -r ; neuere Version von BSD sed , wie auf FreeBSD 10, unterstützt jetzt auch -r , die MacOS-Version ab 10.12 jedoch nicht ).
    Einschränkung : Auch wenn die Verwendung von -r / -E bedeutet, dass Ihr Befehl definitionsgemäß nicht POSIX-kompatibel ist, müssen Sie sich dennoch auf POSIX-EREs (erweiterte reguläre Ausdrücke) beschränken . Leider bedeutet dies, dass Sie nicht mehrere nützliche Konstrukte verwenden können, insbesondere:

    • wortbegrenzte Zusicherungen, da sie plattformspezifisch sind (z. B. \< unter Linux, [[:<]] unter OS X).
    • Rückverweise innerhalb regulärer Ausdrücke (im Gegensatz zu den "Rückverweisen" für Capture-Group-Übereinstimmungen in der Ersetzungszeichenfolge von s Funktionsaufrufen), da BSD sed sie nicht in erweiterten Regex unterstützt (aber seltsamerweise in grundlegende , wo sie POSIX-mandatiert sind).
  • Steuerzeichen-Escape-Sequenzen wie \n und \t :

    • Nehmen Sie in Regex (sowohl in Mustern für die Zeilenauswahl als auch im ersten Argument für die s Funktion) an, dass nur \n als Escape-Sequenz erkannt wird (selten verwendet, da der Musterraum normalerweise eine einzige Zeile ist (ohne \n zu beenden). aber nicht innerhalb einer Zeichenklasse , so dass zB [^\n] nicht funktioniert (wenn Ihre Eingabe keine Steuerzeichen enthält. Außer \t können Sie [^\n] mit [[:print:][:blank:]] [^\n] emulieren. [[:print:][:blank:]] ; andernfalls Steuerzeichen von Splices als Literale [2] ) - enthalten Steuerzeichen normalerweise als Literale , entweder über gespleißte ANSI-C-Anführungszeichenfolgen (z. B. $'\t' ) in Shells, die dies unterstützen ( bash, ksh, zsh ) oder über Befehlssubstitutionen mit printf (z. B. "$(printf '\t')" ) .

      • Nur Linux:
        sed 's/\t/-/' <<<$'a\tb' # -> 'a-b'
      • OSX und Linux:
        sed 's/'$'\t''/-/' <<<$'a\tb' # ANSI C-quoted string
        sed 's/'"$(printf '\t')"'/-/' <<<$'a\tb' # command subst. with printf
    • In Ersetzungszeichenfolgen, die mit dem Befehl s , wird davon ausgegangen, dass KEINE Steuerzeichen-Escape-Sequenzen unterstützt werden , also auch Steuerzeichen. als Literale wie oben.

      • Nur Linux:
        sed 's/-/\t/' <<<$'ab' # -> 'a<tab>b'
      • macOS und Linux:
        sed 's/-/'$'\t''/' <<<'a-b'
        sed 's/-/'"$(printf '\t')"'/' <<<'a-b'
    • Gleiches gilt für die Textargumente zu den Funktionen i und a : Verwenden Sie keine Steuerzeichenfolgen - siehe unten.

  • Beschriftungen und Verzweigungen : Beschriftungen sowie das Argument mit dem Benennungsnamen für die Funktionen b und t müssen entweder von einem wörtlichen Zeilenumbruch oder einem gespleißten $'\n' gefolgt werden . Verwenden Sie alternativ mehrere -e Optionen und beenden Sie jede direkt nach dem Labelnamen.

    • Nur Linux:
      sed -n '/a/ bLBL; d; :LBL p' <<<$'a\nb' # -> 'a'
    • macOS und Linux:
      • EITHER (aktuelle Zeilenumbrüche):
        sed -n '/a/ bLBL d; :LBL p' <<<$'a\nb'
      • ODER (in $\n Instanzen zusammengefügt):
        sed -n '/a/ bLBL'$'\n''d; :LBL'$'\n''p' <<<$'a\nb'
      • ODER (mehrere -e Optionen):
        sed -n -e '/a/ bLBL' -e 'd; :LBL' -e 'p' <<<$'a\nb'
  • Funktionen i und a zum Einfügen / Anfügen von Text : Folgen Sie dem Funktionsnamen mit \ , gefolgt von einem wörtlichen Zeilenvorschub oder einem gespleißten $'\n' bevor Sie das Textargument angeben .

    • Nur Linux:
      sed '1 i new first line' <<<$'a\nb' # -> 'new first line<nl>a<nl>b'
    • OSX und Linux:
      sed -e '1 i\'$'\n''new first line' <<<$'a\nb'
    • Hinweis:
      • Ohne -e ist das Textargument bei der Ausgabe auf macOS (bug?) Unerklärlicherweise nicht newline-terminiert.
      • Verwenden Sie keine Steuerzeichenzeichen wie \n und \t im Textargument, da diese nur unter Linux unterstützt werden.
      • Wenn das Textargument daher tatsächliche innere Zeilenumbrüche enthält, \ -scape diese.
      • Wenn Sie nach dem Textargument zusätzliche Befehle platzieren möchten, müssen Sie es mit einem (nicht verdeckten) Zeilenvorschub (entweder als Literal oder mit einem Splice) beenden oder mit einer separaten Option -e fortfahren (dies ist eine allgemeine Anforderung, die für alle Versionen gilt). .
  • Innerhalb Funktionslisten (Anrufe , die in Mehrfachfunktion eingeschlossen {...} ), sollten Sie auch die letzte Funktion zu beenden, vor dem Schließen } , mit ; .

    • Nur Linux:
      • sed -n '1 {p;q}' <<<$'a\nb' # -> 'a'
    • macOS und Linux:
      • sed -n '1 {p;q;}' <<<$'a\nb'

GNU sed -spezifische Merkmale , die in BSD sed vollständig fehlen:

GNU-Funktionen, die Sie vermissen werden, wenn Sie beide Plattformen unterstützen müssen:


[1] Die macOS sed Version ist älter als die auf anderen BSD-ähnlichen Systemen wie FreeBSD und PC-BSD. Leider bedeutet dies, dass Sie nicht davon ausgehen können, dass Funktionen, die beispielsweise in FreeBSD funktionieren, auf macOS [gleich] funktionieren.

[2] Die ANSI-C-Anführungszeichenfolge $'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177' enthält alle ASCII-Steuerzeichen außer \n (und NUL), sodass Sie es in Kombination mit [:print:] für eine ziemlich robuste Emulation von [^\n] :
'[[:print:]'$'\001\002\003\004\005\006\007\010\011\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\177'']

Ersetzen Sie alle Zeilenumbrüche durch Registerkarten

Hinweis: Der Kürze halber verwenden die Befehle hier-Strings ( <<< ) und ANSI-C-Anführungszeichen ( $'...' ) . Beide Shell-Funktionen funktionieren in bash , ksh und zsh .

# GNU Sed
$ sed ':a;$!{N;ba}; s/\n/\t/g' <<<$'line_1\nline_2\nline_3'
line_1 line_2 line_3

# BSD Sed equivalent (multi-line form)
sed <<<$'line_1\nline_2\nline_3' '
:a
$!{N;ba
}; s/\n/'$'\t''/g'

# BSD Sed equivalent (single-line form, via separate -e options)
sed -e ':a' -e '$!{N;ba' -e '}; s/\n/'$'\t''/g' <<<$'line 1\nline 2\nline 3'

BSD Sed Hinweise:

  • Beachten Sie die Notwendigkeit, Bezeichnungen ( :a ) und Verzweigungsbefehle ( ba ) entweder mit tatsächlichen Zeilenumbrüchen oder mit separaten -e Optionen zu beenden.

  • Da Umschaltanweisungen Steuerzeichen wie \t nicht in der Ersatzzeichenfolge unterstützt werden, ein ANSI - C-Register zitierte Literal wird in die Ersatzzeichenfolge gespleißt.
    (Im Regex- Teil erkennt BSD Sed nur \n als Escape-Sequenz).

Text an eine Zeile mit der Funktion 'a' anhängen

Hinweis: Der Kürze halber verwenden die Befehle hier-Strings ( <<< ) und ANSI-C-Anführungszeichen ( $'...' ) . Beide Shell-Funktionen funktionieren in bash , ksh und zsh .

 # GNU Sed
 $ sed '1 a appended text' <<<'line 1'
 line 1
 appended text

 # BSD Sed (multi-line form)
 sed '1 a\
 appended text' <<<'line 1'

 # BSD Sed (single-line form via a Bash/Ksh/Zsh ANSI C-quoted string)
 sed $'1 a\\\nappended text' <<<'line 1'

Beachten Sie, dass für BSD Seed ein \ gefolgt von einer tatsächlichen Zeilenumbrüche erforderlich ist , um den anzuhängenden Text zu übergeben.
Gleiches gilt für die verwandten Funktionen i (Einfügen) und c (Löschen und Einfügen).



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow