Suchen und Ersetzen von Text in einer Datei mithilfe von Befehlen

Antworten:

1053
sed -i 's/original/new/g' file.txt

Erläuterung:

  • sed = Stream-Editor
  • -i = an Ort und Stelle (dh in die ursprüngliche Datei zurückspeichern)
  • Die Befehlszeichenfolge:

    • s = der Ersatzbefehl
    • original = ein regulärer Ausdruck, der das zu ersetzende Wort beschreibt (oder nur das Wort selbst)
    • new = der zu ersetzende Text
    • g = global (dh alles ersetzen und nicht nur das erste Vorkommen)
  • file.txt = der Dateiname

cscarney
quelle
3
@Akiva Wenn Sie reguläre Sonderzeichen in Ihre Suche einbeziehen, sedwerden diese mit diesen übereinstimmen. Fügen Sie ein -rFlag hinzu, wenn Sie stattdessen erweiterte REs verwenden möchten.
cscarney
32
@mcExchange Wenn es sich speziell um das /Zeichen handelt, mit dem Sie übereinstimmen müssen, können Sie einfach ein anderes Zeichen als Trennzeichen verwenden (z 's_old/text_new/text_g'. B. ). Andernfalls können Sie ein \ vor ein beliebiges setzen $ * . [ \ ^, um das Literalzeichen zu erhalten.
cscarney
3
@BrianZ Für das Dateisystem ist die Ausgabe von sed eine neue Datei mit demselben Namen. Es ist einer der am häufigsten gemeldeten Fehler, die keine Fehler sind
cscarney
16
Der OSX-Befehl sed -i '.bak' 's/original/new/g' file.txtkann auch mit einer Erweiterung sed -i '' 's/original/new/g' file.txtder Länge 0 ausgeführt werden , wodurch keine Sicherung generiert wird.
Kirk
19
MacOS-Benutzer müssen '' 'nach -i als Parameter für -i ed.gs/2016/01/26/os-x-sed-invalid-command-code hinzufügen, damit die Datei überschrieben wird.
geoyws
32

Hierfür gibt es verschiedene Möglichkeiten. Man benutzt sedund Regex. SED ist ein Stream-Editor zum Filtern und Transformieren von Text. Ein Beispiel ist wie folgt:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog

Ein anderer Weg, der sinnvoller sein kann als < strinund > stroutist mit Rohren!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai 
The quick brown fox jumped over the lazy sleeping dog
Marco Ceppi
quelle
6
beachten Sie die catin cat file | sed '...'ist nicht erforderlich. Sie können direkt sagen sed '...' file.
Fedorqui
1
In der Tat kann dies weiter reduziert werden: Die sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarlyDatei wird in regelmäßigen Abständen abgelegt und die 2 Änderungen werden an Ort und Stelle vorgenommen, während ein Backup erstellt wird. Mit time bash -c "$COMMAND"der Zeit lässt sich sagen, dass diese Version ~ 5-mal schneller ist.
pbhj
23

Es gibt eine Vielzahl von Möglichkeiten, dies zu erreichen. Abhängig von der Komplexität dessen, was mit dem Ersetzen von Zeichenfolgen erreicht werden soll, und abhängig von den Tools, mit denen der Benutzer vertraut ist, werden einige Methoden möglicherweise mehr bevorzugt als andere.

In dieser Antwort verwende ich eine einfache input.txtDatei, mit der Sie alle hier aufgeführten Beispiele testen können. Der Inhalt der Datei:

roses are red , violets are blue
This is an input.txt and this doesn't rhyme

BASH

Bash ist eigentlich nicht für die Textverarbeitung gedacht, aber einfache Ersetzungen können durch Parametererweiterung erfolgen , insbesondere können wir hier eine einfache Struktur verwenden ${parameter/old_string/new_string}.

#!/bin/bash
while IFS= read -r line
do
    case "$line" in
       *blue*) printf "%s\n" "${line/blue/azure}" ;;
       *) printf "%s\n" "$line" ;;
    esac
done < input.txt

Dieses kleine Skript ersetzt nicht direkt, dh Sie müssten neuen Text in einer neuen Datei speichern und die alte Datei entfernen oder mv new.txt old.txt

Randbemerkung: Wenn Sie neugierig sind , warum while IFS= read -r ; do ... done < input.txtverwendet wird, ist es im Grunde Art und Weise Shell die Datei Zeile für Zeile zu lesen. Siehe dies als Referenz.

AWK

AWK, ein Textverarbeitungsprogramm, ist für eine solche Aufgabe durchaus geeignet. Es kann einfache und fortgeschrittene Ersetzungen auf der Basis regulärer Ausdrücke durchführen . Es bietet zwei Funktionen: sub()und gsub(). Der erste ersetzt nur das erste Vorkommen, während der zweite - Vorkommen in der gesamten Zeichenfolge ersetzt. Wenn wir zum Beispiel einen String haben one potato two potato, wäre dies das Ergebnis:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana

$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      
one banana two potato 

AWK kann eine Eingabedatei als Argument verwenden. Dasselbe input.txtgilt für:

awk '{sub(/blue/,"azure")}1' input.txt

Abhängig von der Version von AWK, die Sie haben, kann es sein, dass die Bearbeitung an Ort und Stelle erfolgt oder nicht. Daher besteht die übliche Praxis darin, neuen Text zu speichern und zu ersetzen. Zum Beispiel so etwas:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

SED

Sed ist ein Zeileneditor. Es werden auch reguläre Ausdrücke verwendet, aber für einfache Ersetzungen ist es ausreichend, Folgendes zu tun:

sed 's/blue/azure/' input.txt

Das Gute an diesem Tool ist, dass es eine direkte Bearbeitung hat, die Sie mit -iflag aktivieren können .

Perl

Perl ist ein weiteres Tool, das häufig für die Textverarbeitung verwendet wird, aber eine universelle Sprache ist und in Netzwerken, der Systemadministration, Desktop-Apps und vielen anderen Bereichen verwendet wird. Es wurden viele Konzepte / Funktionen aus anderen Sprachen wie C, sed, awk und anderen übernommen. Eine einfache Ersetzung kann folgendermaßen erfolgen:

perl -pe 's/blue/azure/' input.txt

Wie sed hat auch perl das Flag -i.

Python

Diese Sprache ist sehr vielseitig und wird auch in einer Vielzahl von Anwendungen verwendet. Es hat eine Menge Funktionen für die Arbeit mit Strings, unter denen Sie replace(), wenn Sie Variablen wie haben var="Hello World", tun könntenvar.replace("Hello","Good Morning")

Ein einfacher Weg, eine Datei zu lesen und einen String darin zu ersetzen, wäre folgender:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

Mit Python müssen Sie jedoch auch in eine neue Datei ausgeben, was Sie auch innerhalb des Skripts selbst tun können. Zum Beispiel ist hier ein einfacher:

#!/usr/bin/env python
import sys
import os
import tempfile

tmp=tempfile.mkstemp()

with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
    for line in fd1:
        line = line.replace('blue','azure')
        fd2.write(line)

os.rename(tmp[1],sys.argv[1])

Dieses Skript ist input.txtals Kommandozeilenargument aufzurufen. Der genaue Befehl zum Ausführen eines Python-Skripts mit einem Befehlszeilenargument wäre

 $ ./myscript.py input.txt

oder

$ python ./myscript.py input.txt

Vergewissern Sie sich natürlich, dass ./myscript.pysich das in Ihrem aktuellen Arbeitsverzeichnis befindet, und stellen Sie zunächst sicher, dass es mit ausführbar eingestellt istchmod +x ./myscript.py

Python kann auch reguläre Ausdrücke haben, insbesondere gibt es reModule, die re.sub()Funktionen haben, die für fortgeschrittenere Ersetzungen verwendet werden können.

Sergiy Kolodyazhnyy
quelle
1
Schöne Zusammenstellung! Eine andere Möglichkeit, die hier nicht erwähnt wird, ist die Verwendung des trBefehls in Unix
Tapajit Dey,
1
@TapajitDey Ja, tr ist ein weiteres großartiges Werkzeug, aber beachten Sie, dass es für den Ersatz Zeichensätze (zum Beispiel tr abc cdewürde übersetzen azu c, bbis des ein bisschen anders ist zu ersetzen ganze Wörter wie mit. sedOderpython
Sergiy Kolodyazhnyy
22

Sie können Vim im Ex-Modus verwenden:

ex -s -c '%s/OLD/NEW/g|x' file
  1. % Wählen Sie alle Zeilen aus

  2. s Ersatz

  3. g Ersetzen Sie alle Instanzen in jeder Zeile

  4. x schreiben Sie, wenn Änderungen vorgenommen wurden (sie haben) und beenden Sie

Steven Penny
quelle
21

Durch awks gsub Befehl

awk '{gsub(/pattern/,"replacement")}' file

Beispiel:

awk '{gsub(/1/,"0");}' file

Im obigen Beispiel werden alle Einsen durch Nullen ersetzt, unabhängig von der Spalte, in der sie sich befinden.


Wenn Sie eine bestimmte Spalte ersetzen möchten, gehen Sie folgendermaßen vor:

awk '{gsub(/pattern/,"replacement",column_number)}' file

Beispiel:

awk '{gsub(/1/,"0",$1);}' file

Ersetzt 1 nur in der ersten Spalte durch 0.

Durch Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
Avinash Raj
quelle
Ich habe dies auf dem MacOS-Terminal verwendet und es hat nichts getan ...
Jim
Getestet unter Alpine Linux (im Docker-Container) und ohne Ausgabe
Salathiel Genèse
@ SalathielGenèse was versuchst du zu erreichen?
Avinash Raj
Ich schaue mir Dateien mit inotifywaitunter shenv an und berichte Daten im CSV-Format (da das benutzerdefinierte Format fehlerhaft ist). Ich dachte mir dann, dass es keine einfache Möglichkeit gibt, CSV-Dokumente in Shell-Skripten zu verarbeiten ... Und ich möchte, dass es sehr leicht ist. Also habe ich ein ziemlich einfaches Skript gestartet, um CSV zu analysieren und zu melden. Ich habe die CSV-Spezifikation gelesen und festgestellt, dass sie ausgefeilter ist als erwartet, und dass sie in doppelte Anführungszeichen eingeschlossene mehrzeilige Werte unterstützt. sedBei der Tokenisierung habe ich mich darauf verlassen, aber bald wurde mir klar, dass selbst bei sedMultilines bis zu zwei Leitungen möglich sind. Was ist, wenn einer meiner CSV-Werte mehr als zwei Zeilen umfasst?
Salathiel Genèse
Besser, Sie stellen Ihr Problem als Frage.
Avinash Raj
8

sedist die s tream ed itor , in die Sie verwenden können |(Rohr) zu senden Standard - Streams (STDIN und STDOUT spezifisch) durch sedund verändern sie im Fluge programmatisch, es ist ein praktisches Tool , in der Philosophie , Tradition Unix zu machen; Sie können Dateien jedoch auch direkt bearbeiten, indem Sie den -iunten angegebenen Parameter verwenden.
Beachten Sie Folgendes :

sed -i -e 's/few/asd/g' hello.txt

s/wird verwendet s ubstitute den gefundenen Ausdruck fewmit asd:

Die Wenigen, die Tapferen.


Der Asd, der Tapfere.

/gsteht für "global" und bedeutet dies für die gesamte Zeile. Wenn Sie das /g(mit s/few/asd/, es muss immer drei Schrägstriche geben, egal was passiert) weglassen und fewzweimal in derselben Zeile erscheinen, wird nur die erste fewgeändert in asd:

Die wenigen Männer, die wenigen Frauen, die Mutigen.


Die Männer, die wenigen Frauen, die Mutigen.

Dies ist unter bestimmten Umständen hilfreich, z. B. beim Ändern von Sonderzeichen am Anfang von Zeilen (z. B. durch Ersetzen der Größer-als-Symbole, mit denen manche Benutzer vorheriges Material in E-Mail-Threads mit einem horizontalen Tabulator zitieren, während später in der Zeile eine zitierte algebraische Ungleichung verbleibt unberührt), aber in Ihrem Beispiel, in dem Sie angeben, dass überall , wo esfew vorkommt, es ersetzt werden soll, stellen Sie sicher, dass Sie das haben /g.

Die folgenden zwei Optionen (Flags) werden zu einer zusammengefasst -ie:

-iOption wird verwendet , um zu bearbeiten i n auf die Datei platzieren hello.txt.

-eOption gibt die e xpression / Befehl ausgeführt werden soll, in diesem Fall s/.

Hinweis: Es ist wichtig, dass Sie -i -ezum Suchen / Ersetzen verwenden. In diesem -ieFall erstellen Sie eine Sicherungskopie jeder Datei, an die der Buchstabe "e" angehängt ist.

Chaminda Bandara
quelle
2

Das können Sie machen:

locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g" 

Beispiele: Um alle Vorkommen [logdir ',' '] (ohne []) durch [logdir', os.getcwd ()] in allen Dateien zu ersetzen, die das Ergebnis des Befehls locate sind, gehen Sie wie folgt vor:

ex1:

locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"

ex2:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

Wobei [tensorboard / program.py] die zu durchsuchende Datei ist

Nguyễn Tuấn Anh
quelle
Hallo. Ihre Auswahl an Zeichenfolgen ( logdir', ''-> /logdir', os.getcwd()) macht es schwierig, diese Antwort zu analysieren. Außerdem sollte angegeben werden, dass Ihre Antwort zuerst die zu verwendenden Dateien findet, da dies nicht Teil der Frage ist.
Mwfearnley
Hallo, diese Antwort ist sowohl Suchen als auch Ersetzen, wenn <alter Text> in der Datei gefunden wurde.
Nguyễn Tuấn Anh
Ich wähle diese Antwort für alle, die Tensorboard in Keras verwenden und den Befehl von: tensorboard --logdir = '/ path / to / log / folder /' ändern möchten, um: tensorboard nur zu verwenden, wenn sie im Protokollordner bleiben. es ist sehr praktisch
Nguyễn Tuấn Anh