it-swarm.com.de

Groß- und Kleinschreibung nicht suchen und durch Sed ersetzen

Ich versuche, SED zu verwenden, um Text aus einer Protokolldatei zu extrahieren.

Ich kann ohne großen Aufwand suchen und ersetzen:

sed 's/foo/bar/' mylog.txt

Ich möchte jedoch die Suche unabhängig von der Groß- und Kleinschreibung machen. Nach dem, was ich gegoogelt habe, sieht es so aus, als würde das Anhängen von i an das Ende des Befehls funktionieren:

sed 's/foo/bar/i' mylog.txt

Dies gibt mir jedoch eine Fehlermeldung:

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'

Was läuft hier falsch und wie kann ich es beheben?

Ich bin bei macOS, falls es wichtig ist.

67
Craig Walker

Um es klar auszudrücken: Auf macOS - ab Mojave (10.14) - sed - welches ist das BSD Implementierung - unterstützt KEINE Übereinstimmung ohne Berücksichtigung der Groß-/Kleinschreibung - kaum zu glauben, aber wahr. Die ehemals akzeptierte Antwort , die selbst einen GNUsed -Befehl anzeigt, hat diesen Status aufgrund der Perl- erhalten. basierte Lösung in den Kommentaren erwähnt.

Damit diese Perl-Lösung auch mit Fremdzeichen über UTF funktioniert -8, benutze etwas wie:

Perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
  • -C aktiviert die UTF-8-Unterstützung für Streams und Dateien, sofern das aktuelle Gebietsschema UTF-8-basiert ist.
  • -Mutf8 weist Perl an, den Quellcode als UTF-8 zu interpretieren (in diesem Fall die Zeichenfolge, die an -pe übergeben wird) - dies ist die kürzere Entsprechung von je ausführlicher -e 'use utf8;'.Danke, Mark Reed

(Beachten Sie, dass die Verwendung von awk ebenfalls keine Option ist , da awk unter macOS (dh ) BWK awk , auch bekannt als BSD awk ) scheint die Gebietsschemata überhaupt nicht zu kennen - seine Funktionen tolower() und toupper() ignorieren Fremdzeichen (und sub()/gsub() haben zunächst keine Flags für die Unterscheidung zwischen Groß- und Kleinschreibung.)

65
mklement0

Anmerkung des Herausgebers : Diese Lösung funktioniert nicht auf macOS (out of the box), da sie nur fürGNUsed gilt, während macOS mitBSDsed geliefert wird.

Das "Ich" groß machen.

sed 's/foo/bar/I' file
56
Wesley Rice

Eine weitere Problemumgehung für sed unter Mac OS X besteht darin, gsedfr von MacPorts oder HomeBrew zu installieren und dann den Aliasnamen sed='gsed' zu erstellen.

22
user4854746

Das sed FAQ befasst sich mit der eng verwandten Groß-/Kleinschreibung search. Es weist darauf hin, dass a) viele Versionen von Sed eine Flagge dafür unterstützen und b) es in Sed nicht möglich ist, awk oder Perl zu verwenden.

Um dies in POSIX sed zu tun, schlagen sie drei Optionen vor (hier für Substitutionen angepasst):

  1. Konvertierung in Großbuchstaben und Speicherung der ursprünglichen Zeile im Speicherplatz; Dies funktioniert jedoch nicht für Substitutionen, da der ursprüngliche Inhalt vor dem Drucken wiederhergestellt wird. Daher eignet er sich nur zum Einfügen oder Hinzufügen von Zeilen, die auf einer Übereinstimmung ohne Berücksichtigung der Groß- und Kleinschreibung basieren.

  2. Möglicherweise sind die Möglichkeiten auf FOO, Foo und foo beschränkt. Diese können durch abgedeckt werden

    s/FOO/bar/;s/[Ff]oo/bar/
    
  3. Um nach allen möglichen Übereinstimmungen zu suchen, können Sie für jedes Zeichen Klammerausdrücke verwenden:

    s/[Ff][Oo][Oo]/bar/
    
2
Benjamin W.

Die Mac-Version von sed scheint etwas eingeschränkt zu sein. Um dies zu umgehen, verwenden Sie einen Linux-Container (über Docker), der eine verwendbare Version von sed hat:

cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig'
1
user1307434

Ich hatte ein ähnliches Bedürfnis und kam dazu:

diesen Befehl, um einfach alle Dateien zu finden:

grep -i -l -r foo ./* 

this, um this_Shell.sh auszuschließen (falls Sie den Befehl in ein Skript namens this_Shell.sh einfügen), geben Sie die Ausgabe in die Konsole ein, um zu sehen, was passiert ist, und verwenden Sie dann sed für jeden gefundenen Dateinamen, um die Textfoo mit Bar:

grep -i -l -r --exclude "this_Shell.sh" foo ./* | tee  /dev/fd/2 | while read -r x; do sed -b -i 's/foo/bar/gi' "$x"; done 

Ich entschied mich für diese Methode, da ich nicht alle Zeitstempel für nicht geänderte Dateien geändert haben wollte. Durch das Einspeisen des grep-Ergebnisses können nur die Dateien mit dem Zieltext betrachtet werden (daher wird möglicherweise auch die Leistung/Geschwindigkeit verbessert).

stellen Sie sicher, dass Sie Ihre Dateien sichern und testen, bevor Sie sie verwenden. Funktioniert in einigen Umgebungen möglicherweise nicht für Dateien mit eingebetteten Leerzeichen. (?)

0
gojimmypi

Wenn Sie zuerst einen Musterabgleich durchführen, z.

/pattern/s/xx/yy/g

dann möchten Sie die I nach dem Muster setzen:

/pattern/Is/xx/yy/g

Beispiel:

echo Fred | sed '/fred/Is//willma/g'

gibt willma zurück; Ohne I wird der String unberührt (Fred) zurückgegeben.

0
CBB