Wie finde und ersetze ich einen String ohne den Befehl Sed?


16

Wie wir alle wissen, sedist sehr effizient String finden, zum Beispiel ‚a‘ und ersetzen Sie es auf ‚b‘ zu finden und ersetzen: sed 's/a/b/g'.

Ist es möglich, dies mit einem anderen Befehl oder Shell-Skript zu tun sed?

Dies ist für ein abgeschnittenes Linux-System für das Fernsehen, das den sedBefehl nicht hat . Also muss ich stattdessen andere Befehle oder Skripte verwendensed 's/a/b/g'. –


Eigentlich ist das nur eine Substitution auf der Basis regulärer Ausdrücke. Jedes Werkzeug oder Sprache fähig so etwas zu handhaben in der Lage, das gleiche zu tun, sondern mit verschiedener Syntax: $var=~s/a/b/g, gsub(/a/,"b",var), var.gsub(/a/,'b'), var.replace(/a/g,'b'), preg_replace("/a/","b",$var), regsub -all a b $var. Daneben können viele Tools und Sprachen auch Zeichenfolgen im Klartext ersetzen. Deine Frage ist also irgendwie weit gefasst.
Manatwork

1
Warum? Welches Problem versuchen Sie zu lösen?
Gilles 'SO- hör auf böse zu sein'

Ein abgeschnittenes Linux-System fürs Fernsehen hat nicht den Befehl gegeben. Also muss ich einen anderen Befehl oder ein anderes Skript verwenden, um sed 's / a / b / g' zu ersetzen.
Binghenzq

Antworten:


12

Ja, es gibt verschiedene Möglichkeiten, dies zu tun. Sie können auch awk, perloder verwenden bash, um diese Aktivitäten auszuführen. Im Allgemeinen sedist es jedoch wahrscheinlich das am besten geeignete Werkzeug für diese Art von Aufgaben.

Beispiele

Angenommen, ich habe diese Beispieldaten in einer Datei data.txt:

foo bar 12,300.50
foo bar 2,300.50
abc xyz 1,22,300.50

awk

$ awk '{gsub("foo", "foofoofoo", $0); print}' data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Perl

$ perl -pe "s/foo/foofoofoo/g" data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Inline-Bearbeitung

Die obigen Beispiele können auch die Dateien direkt ändern. Das Perl-Beispiel ist trivial. Fügen Sie einfach den -iSchalter hinzu.

$ perl -pie "s/foo/foofoofoo/g" data.txt 

Denn awkes ist ein bisschen weniger direkt, aber genauso effektiv:

$ { rm data.txt && awk '{gsub("foo", "foofoofoo", $0); print}' > data.txt; } < data.txt

Diese Methode erstellt eine Sub-Shell mit den geschweiften Klammern "{...}", in die die Datei folgendermaßen umgeleitet wird:

$ { ... } < data.txt

Sobald die Datei in die Sub-Shell umgeleitet wurde, wird sie gelöscht und dann mit awkdem Inhalt der Datei abgeglichen, die in die Sub-Shells STDIN eingelesen wurde. Dieser Inhalt wird dann von verarbeitet awkund in den gleichen Dateinamen zurückgeschrieben, den wir gerade gelöscht haben, und ersetzt ihn effektiv.


Vielen Dank für Ihre Antwort und ich werde es am nächsten Arbeitstag versuchen. Aber ich bin nicht sicher, ob es funktioniert, weil einige Befehle in einem abgeschnittenen Linux-System von TV, wie "sed", möglicherweise nicht vorhanden sind. Also möchte ich immer noch den Befehl "find" verwenden. , "grep" und so weiter, um es zu lösen.
Binghenzq

@binghenzq - Ich habe Beispiele hinzugefügt, die die Datei inline bearbeiten.
slm

-1 Ich habe selten abgelehnt, aber in diesem Fall schien der Punkt der Frage eine einfachere Methode zu sein als andere, komplexere und wahrscheinlich auch abhängige. Wenn die Frage nur nach Alternativen für eine vollständige * nix-Maschineninstallation wäre, würde ich diese ansonsten gute Antwort wahrscheinlich +1 geben.
Michael Durrant

@MichaelDurrant - Ich habe gerade die aufwändigen Inline-Änderungen hinzugefügt, die das OP für sie angefordert hat. Außerdem hat das OP die Anforderung festgelegt, NICHT mit sednicht I zu arbeiten. Sed ist das geeignete Werkzeug, um solche Substitutionen durchzuführen, und er bittet offensichtlich darum, die Rollen dieser Werkzeuge besser zu verstehen sie warum. Zu oft sagen die Leute im Wissen einfach "Tu es nicht", ohne zu erklären warum, also bin ich es. Aber danke, dass du wenigstens einen Kommentar hinterlässt, warum du DV.
SLM

Klar, ich fand es auch in jeder anderen Hinsicht eine großartige Antwort. Ja, ich hasse -1 ohne Erklärung.
Michael Durrant

13

Die klassische Alternative für Einzelbuchstabenersetzungen ist der trBefehl, der auf nahezu jedem System verfügbar sein sollte:

$ echo "foobar" | tr a b   
foobbr

trist besser als seddies tatsächlich , da die Verwendung sed(allein lassen perloder awk) für einzelne Buchstabenersetzungen ist ein Schlitten Hammer wie mit einer Fliege zu töten.

grep ist nicht dafür ausgelegt, es ändert seine Eingabe nicht, es durchsucht sie nur.

Alternativ können Sie die Substitutionsfunktionen einiger Shells verwenden. Hier verwenden ksh, zshoder bashSyntax:

$ foo="foobar"
$ echo "${foo//a/b}"
foobbr

Wir könnten Ihnen genauere Antworten geben, wenn Sie genau erklären, welches Problem Sie lösen möchten.


Gibt es eine Option, Groß- und Kleinschreibung zu ignorieren ${foo//a/b}?
AlikElzin-kilaka

@ AlikElzin-kilaka Ich fürchte nicht. Sie werden etwas anspruchsvollere wie zum Beispiel verwenden: echo "$foo" | sed 's/a/b/ioder eine Zeichenklasse geben: echo ${foo//[aA]/b}.
Terdon

4

Sie können Vim im Ex-Modus verwenden:

ex -s -c '%s/a/b/g|x' file
  1. % wähle alle Zeilen aus

  2. s Ersatz

  3. g global ersetzen

  4. x speichern und schließen


vielen Dank. Nur zum Hinzufügen: -c flag führt den Befehl zu Beginn der Bearbeitung aus (da ex ein Editor ist) und -s flag ist entweder ein Skriptmodus, der die Rückmeldung deaktiviert, oder, wie manche sagen, ein Slient-Modus. Weitere Informationen finden Sie unter: ex-vi.sourceforge.net/ex.html
Jimmy MG Lim

3

Wenn Sie mit einer Datei anstatt mit einem Stream arbeiten, können Sie den Standard-Texteditor verwenden ed:

printf '%s\n' ',s/a/b/g' w q | ed file.txt

Dies sollte auf jedem * nix verfügbar sein. Das Komma in ',s/a/b/g'weist Sie edan, in jeder Zeile zu arbeiten (Sie können es auch verwenden %, was besser bekannt ist, wenn Sie an vim gewöhnt sind), und der Rest ist ein standardmäßiges Suchen und Ersetzen. wWeist es an, die Datei zu schreiben (zu speichern) qund zu beenden.

Beachten Sie, dass im Gegensatz zur -iOption sed (und ähnlichen Optionen in anderen Tools) die Datei hierdurch tatsächlich direkt bearbeitet wird, anstatt mit temporären Dateien zu schummeln.

Ich glaube nicht, dass es möglich ist, dies mit Streams zum Laufen zu bringen, aber dann weiß ich nicht viel darüber edund würde mich nicht wundern, wenn es tatsächlich über diese Fähigkeit verfügt (die Unix-Philosophie ist das, was sie ist).


2

Verwenden Sie den Befehl ancestor (in dem -sstill (silent) und das Komma vor den Befehlen bedeutet, dass in allen Zeilen ausgeführt wird):

Einfach auf STDOUT drucken :

ed -s file <<!
,s/a/b/g
,p
q
!

an Ort und Stelle ersetzen:

ed -s file <<!
,s/a/b/g
w
q
!
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.