2010-12-10 30 views
60

Ich versuche, SED zu verwenden, um Text aus einer Protokolldatei zu extrahieren.Case-insensitive suchen und ersetzen mit sed

Ich kann ohne allzu viel Mühe ein Such- und ersetzen tun:

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

Allerdings möchte ich die Suche Groß- und Kleinschreibung machen. Von dem, was ich gegoogelt habe, sieht es aus wie das Anhängen "i" am Ende des Befehls sollte funktionieren:

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

aber das gibt mir eine Fehlermeldung:

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

Was läuft hier falsch und wie repariere ich es?

Ich bin auf OS X, falls es darauf ankommt.

+0

Haben Sie Capital 'I' versucht? – Lazer

+0

@Lazer: Ich habe, aber es hat nicht funktioniert. Es ist mir genug ratlos, dass ich eine Bitte um Hilfe bei der SO veröffentliche. :-( –

+2

Können Sie versuchen, Ihre Kopie von sed zu aktualisieren? 'I 'ist eine GNU-Erweiterung, die möglicherweise nicht mit Ihrer Kopie von sed. – Lazer

Antwort

53

Um klar zu sagen: Auf macOS (OS X) - wie von Sierra (10.12) - sed - das ist die BSD Implementierung ist - NICHT unterstützt Groß- und Kleinschreibung passend - schwer zu glauben, , aber richtig. Die formerly accepted answer, die selbst einen GNUsed Befehl zeigt, erlangte diesen Status aufgrund der -basierten Lösung, die in den Kommentaren erwähnt wird.

Um auch über UTF-8, verwenden Sie so etwas wie die Perl Lösung Arbeit mit fremden Zeichen zu machen:

perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo" 
  • -C schaltet UTF-8-Unterstützung für Streams und Dateien, Angenommen, das aktuelle Gebietsschema ist UTF-8-basiert.
  • -Mutf8 erzählt Perl den Quellcode als UTF-8 (in diesem Fall die Zeichenfolge zu -pe bestanden) zu interpretieren - das ist die kürzere Äquivalent des ausführlicheren -e 'use utf8;' - danke, @ Mark Reed.

(Beachten Sie, dass awk Verwendung erscheint keine Option ist entweder, wie awk auf OS X (dh BWK awk, auch bekannt als BSD awk) vollständig gänzlich von Schauplätzen nicht bewusst zu sein - seine tolower() und toupper() Funktionen ignorieren fremde Zeichen (und sub()/gsub() nicht case-Unempfindlichkeit Fahnen zu beginnen haben.))

+0

In der 'perl'-Befehlszeile können Sie immer' -mblah' anstelle von '-e 'blah' verwenden. –

+0

Tippfehler - sollte groß geschrieben werden, damit dieser funktioniert. 'Perl -C -Mutf8 -pe 's/öœ/oo/i' <<<" FÖŒ "# => Foo' –

+0

@MarkReed: Danke - Ich habe die Antwort aktualisiert. – mklement0

52

Nutze das 'I'.

sed 's/foo/bar/I' file 
+2

Ich sah das auch, und versuchte es ... aber ich bekomme immer noch die gleiche Fehlermeldung. –

+13

BSD sed hat eine Menge Einschränkungen, so scheint es. Ich würde das in PERL machen (d. H. Perl -pe 's/foo/bar/i'), wenn das der Fall ist. –

+0

Ihr Perl-Befehl hat funktioniert. Ich werde dir dafür eine Erwähnung geben. –

1

Die Mac-Version von sed scheint ein wenig begrenzt.Eine Möglichkeit, dies zu umgehen, ist ein Linux-Container zu verwenden (über Docker), die eine nutzbare Version von sed hat:

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

Dies ist eine besonders abscheuliche Sache zu tun. Wenn jemand ernsthaft darüber nachdenkt, installieren Sie einfach ein GNU sed lokal. – ocodo

17

Eine andere Work-around für sed auf Mac OS X ist gsed von MacPorts oder HomeBrew zu installieren und Erstellen Sie dann den Alias ​​sed='gsed'.

+0

gsed "s/a/b/Ig" funktioniert, danke! Warum sollte eine gut funktionierende Antwort einen Downvote bekommen? –

+2

Diese Antwort ist großartig. benutze 'brew install gnu-sed' ging dann zu meinem ~/.bash_profile und fügte den Alias ​​hinzu. Danke @davmat – ThinkBonobo

+5

Besser zu 'brew install gnu-sed --mit-default-Namen' - dies überschreibt die Standard-' sed'. – Mar0ux

-2

sed 's/string1/string2/Ig' Großbuchstabe I ist eine Option, die zum Suchen eines Strings unabhängig von der Groß-/Kleinschreibung verwendet werden kann.

0

hatte ich ein ähnliches Bedürfnis, und kam mit dieser: this_shell.sh (im Fall ausschließen Sie setzen den Befehl

grep -i -l -r foo ./* 

dieses:

dieser Befehl alle Dateien einfach finden in einem Skript this_shell.sh) genannt, zweigen an der Konsole die Ausgabe zu sehen, was passiert ist, und dann auf jedem Dateinamen den Text foo mit Bar gefunden sed benutzen ersetzen:

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 habe diese Methode gewählt, da ich nicht wollte, dass alle Zeitstempel für nicht modifizierte Dateien geändert wurden. Wenn das grep-Ergebnis eingegeben wird, können nur die Dateien mit dem Zieltext betrachtet werden (was wahrscheinlich auch die Leistung/Geschwindigkeit verbessern kann)

sicher sein, Ihre Dateien zu sichern & vor der Verwendung testen. Funktioniert in einigen Umgebungen möglicherweise nicht für Dateien mit eingebetteten Leerzeichen. (?)

0

Wenn Sie Muster tun passende erste eg/Muster/s/xx/yy/g

dann wollen Sie setzen die "I" nach dem Muster/Muster/Ist/xx/yy/g

Beispiel: echo Fred | sed '/ fred/Is // willma/g' gibt willma zurück ... ohne das ich die Saite zurücksendet (Fred)