@ruakh wie schreibe ich diese Aussage mit einer oder Bedingung. Nur wenn ich Suzi oder Marry durch eine neue Saite ersetzen möchte.
Priyatham51
3
@ Priyatham51: Dafür gibt es keine eingebaute Funktion. Ersetzen Sie einfach einen und dann den anderen.
Ruakh
4
@Bu: Nein, denn \nin diesem Zusammenhang würde sich selbst keine Newline darstellen. Ich habe Bash momentan nicht zum Testen zur Hand, aber Sie sollten in der Lage sein, so etwas wie zu schreiben $STRING="${STRING/$'\n'/<br />}". (Obwohl Sie wahrscheinlich wollen STRING//- ersetzen Sie alle - anstatt nur STRING/.)
Ruakh
25
Um klar zu sein, da mich das ein bisschen verwirrt hat, muss der erste Teil eine variable Referenz sein. Das kannst du nicht machen echo ${my string foo/foo/bar}. Sie würden braucheninput="my string foo"; echo ${input/foo/bar}
Henrik N
2
@mgutt: Diese Antwort verweist auf die entsprechende Dokumentation. Die Dokumentation ist nicht perfekt - anstatt //direkt zu erwähnen , wird beispielsweise erwähnt, was passiert, wenn das Muster mit ' /' beginnt “(was nicht einmal genau ist, da der Rest dieses Satzes davon ausgeht, dass das Extra /nicht Teil von ist das Muster) - aber ich kenne keine bessere Quelle.
Ruakh
208
Dies kann vollständig mit Bash-String-Manipulation erfolgen:
first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}
Das wird nur das erste Vorkommen ersetzen; Um sie alle zu ersetzen, verdoppeln Sie den ersten Schrägstrich:
first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}# first is now "Sara, Sara, Sara"
Was bringt es, eine Antwort zu haben, die die akzeptierte dupliziert, anstatt die akzeptierte mit der globalen Ersatzoption zu bearbeiten? Und das Hinzufügen dieser regulären Ausdrücke wird dabei unterstützt. Und erklären, was mit "Bad Substitution" los ist. Sie haben genug Punkte, @ Kevin :)
Dan Dascalescu
6
Es scheint, dass beide genau in der gleichen Minute geantwortet haben: O
Jamie Hutber
76
Für Dash funktionieren alle vorherigen Beiträge nicht
Die POSIX- shkompatible Lösung lautet:
result=$(echo "$firstString"| sed "s/Suzi/$secondString/")
Ich habe folgendes: $ echo $ (echo $ firstString | sed 's / Suzi / $ secondString / g') Ich liebe $ secondString und Marry
Qstnr_La
2
@ Qstnr_La verwenden doppelte Anführungszeichen für die Substitution von Variablen:result=$(echo $firstString | sed "s/Suzi/$secondString/g")
emc
1
Plus 1, um zu zeigen, wie auch eine Variable ausgegeben wird. Vielen Dank!
Chef Pharao
2
Ich habe die einfachen Anführungszeichen korrigiert und auch die fehlenden Anführungszeichen um das echoArgument hinzugefügt . Es funktioniert täuschend ohne Anführungszeichen mit einfachen Zeichenfolgen, bricht jedoch leicht bei nicht trivialen Eingabezeichenfolgen (unregelmäßiger Abstand, Shell-Metazeichen usw.).
Tripleee
In sh (AWS Codebuild / Ubuntu sh) habe ich festgestellt, dass ich am Ende einen einzelnen Schrägstrich brauche, keinen doppelten. Ich werde den Kommentar bearbeiten, da die obigen Kommentare auch einen einzelnen Schrägstrich zeigen.
Sie brauchen Sed dafür nicht wirklich; Bash unterstützt diese Art von Ersatz nativ.
Ruakh
12
Ich denke, dies ist mit "bash" markiert, kam aber hierher, weil es etwas Einfaches für eine andere Shell brauchte. Dies ist eine schöne prägnante Alternative zu dem, was wiki.ubuntu.com/… so aussehen ließ, als würde ich es brauchen.
Natevw
3
Dies funktioniert hervorragend für Ash / Dash oder andere POSIX sh.
Yoshua Wuyts
2
Ich erhalte den Fehler sed: -e Ausdruck # 1, Zeichen 9: Unbekannte Option für `s
Nam G VU
1
Erste Antwort, die mit stdin funktioniert, ideal für Pipelining-Strings.
Dinei
46
Es ist besser, bash zu verwenden, als sedwenn Strings RegExp-Zeichen haben.
echo ${first_string/Suzi/$second_string}
Es ist portabel für Windows und funktioniert mit mindestens so alt wie Bash 3.1.
Um zu zeigen, dass Sie sich keine großen Sorgen um die Flucht machen müssen, drehen wir Folgendes:
/home/name/foo/bar
Das sehr gut finden:
~/foo/bar
Aber nur wenn /home/nameam Anfang ist. Wir brauchen nicht sed!
Da bash gibt uns magische Variablen $PWDund $HOMEkönnen wir:
echo "${PWD/#$HOME/\~}"
EDIT: Danke für Mark Haferkamp in den Kommentaren für den Hinweis zum Zitieren / Entkommen ~. *
Beachten Sie, wie die Variable $HOMESchrägstriche enthält, aber dies hat nichts kaputt gemacht.
Diese Antwort hat mich daran gehindert, sedden pwdBefehl zu verwenden, um zu vermeiden, dass bei jeder Ausführung meiner benutzerdefinierten Datei eine neue Variable definiert wird $PS1. Bietet Bash eine allgemeinere Möglichkeit als magische Variablen, die Ausgabe eines Befehls zum Ersetzen von Zeichenfolgen zu verwenden? Was Ihren Code angeht, musste ich mich dem entziehen ~, um Bash davon abzuhalten, ihn in $ HOME zu erweitern. Was macht das #in Ihrem Befehl?
Mark Haferkamp
1
@MarkHaferkamp Siehe den Link "Weiterführende Literatur empfohlen". Über "Flucht vor dem ~": Beachten Sie, wie ich Sachen zitiert habe. Denken Sie daran, immer Sachen zu zitieren! Und dies funktioniert nicht nur für magische Variablen: Jede Variable kann innerhalb von Bash ersetzt, die Länge der Zeichenfolge ermittelt und vieles mehr werden. Herzlichen Glückwunsch zum $PS1schnellen Versuch : Sie könnten auch daran interessiert sein, $PROMPT_COMMANDob Sie sich in einer anderen Programmiersprache besser auskennen und eine kompilierte Eingabeaufforderung codieren möchten.
Camilo Martin
Der Link "Weiterlesen" erklärt das "#". Auf Bash 4.3.30, echo "${PWD/#$HOME/~}"ersetzt nicht meine $HOMEmit ~. Ersetzen ~durch \~oder '~'funktioniert. Alle diese Arbeiten an Bash 4.2.53 in einer anderen Distribution. Können Sie bitte Ihren Beitrag aktualisieren, um ihn ~für eine bessere Kompatibilität zu zitieren oder zu umgehen? Was ich mit meiner Frage "magische Variablen" meinte, war: Kann ich Bashs Variablensubstitution beispielsweise für die Ausgabe von verwenden, unameohne sie zuerst als Variable zu speichern? Was meine persönlichen $PROMPT_COMMAND, ist es kompliziert .
Mark Haferkamp
@ MarkHaferkamp Whoa, du hast vollkommen recht, mein schlechtes. Aktualisiert die Antwort jetzt.
Camilo Martin
1
@ MarkHaferkamp Bash und seine obskuren Fallstricke ...: P
Camilo Martin
19
Wenn Sie morgen entscheiden, dass Sie Marry nicht lieben, kann sie auch ersetzt werden:
Da kann ich keinen Kommentar hinzufügen. @ruaka Um das Beispiel besser lesbar zu machen, schreiben Sie es so
full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}
Bis ich zu Ihrem Beispiel kam, hatte ich die Reihenfolge umgekehrt verstanden. Dies half zu klären, was passiert
raghav710
5
Reine POSIX - Shell - Methode, die im Gegensatz zu Roman Kazanovskyi ‚s sed-basierte Antwort keine externen Tools benötigt, nur um die eigene Mutter Shell Parameter Erweiterungen . Beachten Sie, dass lange Dateinamen minimiert werden, damit der Code besser in eine Zeile passt:
f="I love Suzi and Marry"
s=Sara
t=Suzi["${f%$t*}"!="$f"]&& f="${f%$t*}$s${f#*$t}"
echo "$f"
Ausgabe:
I love Sara and Marry
Wie es funktioniert:
Kleinstes Suffixmuster entfernen. "${f%$t*}"gibt " I love" zurück, wenn das Suffix $t" Suzi*" in $f" " steht. I loveSuzi and Marry
Aber wenn t=Zelda, dann "${f%$t*}"löscht nichts und gibt die gesamte Zeichenfolge " I love Suzi and Marry" zurück.
Dies wird zu Test verwendet , wenn $tin $fmit [ "${f%$t*}" != "$f" ]dem bewerten wird wahr , wenn die $fZeichenfolge „ Suzi*“ und falsch , wenn nicht.
Wenn der Test true zurückgibt , erstellen Sie die gewünschte Zeichenfolge mit " Kleinstes Suffixmuster entfernen${f%$t*} " I love"und" Kleinstes Präfixmuster entfernen${f#*$t} " and Marry", wobei die zweite Zeichenfolge $s" Sara" dazwischen liegt.
Dieser Trick ist der richtige Weg, wenn das, was Sie teilen möchten, nicht in einer Variablen, sondern in einer Textdatei enthalten ist. Danke, @Payam!
Felipe SS Schneider
2
echo [string]| sed "s/[original]/[target]/g"
"s" bedeutet "Ersatz"
"g" bedeutet "global, alle übereinstimmenden Vorkommen"
Antworten:
Verwenden Sie Folgendes, um das erste Auftreten eines Musters durch eine bestimmte Zeichenfolge zu ersetzen :
${parameter/pattern/string}
Verwenden Sie zum Ersetzen aller Vorkommen Folgendes :
${parameter//pattern/string}
(Dies ist in dokumentiert das Bash - Referenzhandbuch , §3.5.3 "Shell Parameter Expansion" .)
Beachten Sie, dass diese Funktion nicht von POSIX spezifiziert wird - es handelt sich um eine Bash-Erweiterung -, sodass nicht alle Unix-Shells sie implementieren. Die relevante POSIX-Dokumentation finden Sie in den Open Group Technical Standard- Basisspezifikationen , Ausgabe 7 , Shell & Utilities- Volume, §2.6.2 "Parametererweiterung" .
quelle
\n
in diesem Zusammenhang würde sich selbst keine Newline darstellen. Ich habe Bash momentan nicht zum Testen zur Hand, aber Sie sollten in der Lage sein, so etwas wie zu schreiben$STRING="${STRING/$'\n'/<br />}"
. (Obwohl Sie wahrscheinlich wollenSTRING//
- ersetzen Sie alle - anstatt nurSTRING/
.)echo ${my string foo/foo/bar}
. Sie würden braucheninput="my string foo"; echo ${input/foo/bar}
//
direkt zu erwähnen , wird beispielsweise erwähnt, was passiert, wenn das Muster mit '/
' beginnt “(was nicht einmal genau ist, da der Rest dieses Satzes davon ausgeht, dass das Extra/
nicht Teil von ist das Muster) - aber ich kenne keine bessere Quelle.Dies kann vollständig mit Bash-String-Manipulation erfolgen:
Das wird nur das erste Vorkommen ersetzen; Um sie alle zu ersetzen, verdoppeln Sie den ersten Schrägstrich:
quelle
Für Dash funktionieren alle vorherigen Beiträge nicht
Die POSIX-
sh
kompatible Lösung lautet:quelle
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echo
Argument hinzugefügt . Es funktioniert täuschend ohne Anführungszeichen mit einfachen Zeichenfolgen, bricht jedoch leicht bei nicht trivialen Eingabezeichenfolgen (unregelmäßiger Abstand, Shell-Metazeichen usw.).Versuche dies:
quelle
Es ist besser, bash zu verwenden, als
sed
wenn Strings RegExp-Zeichen haben.Es ist portabel für Windows und funktioniert mit mindestens so alt wie Bash 3.1.
Um zu zeigen, dass Sie sich keine großen Sorgen um die Flucht machen müssen, drehen wir Folgendes:
Das sehr gut finden:
Aber nur wenn
/home/name
am Anfang ist. Wir brauchen nichtsed
!Da bash gibt uns magische Variablen
$PWD
und$HOME
können wir:EDIT: Danke für Mark Haferkamp in den Kommentaren für den Hinweis zum Zitieren / Entkommen
~
. *Beachten Sie, wie die Variable
$HOME
Schrägstriche enthält, aber dies hat nichts kaputt gemacht.Weiterführende Literatur: Advanced Bash-Scripting Guide .
Wenn die Verwendung
sed
ein Muss ist, müssen Sie jedem Zeichen entkommen .quelle
sed
denpwd
Befehl zu verwenden, um zu vermeiden, dass bei jeder Ausführung meiner benutzerdefinierten Datei eine neue Variable definiert wird$PS1
. Bietet Bash eine allgemeinere Möglichkeit als magische Variablen, die Ausgabe eines Befehls zum Ersetzen von Zeichenfolgen zu verwenden? Was Ihren Code angeht, musste ich mich dem entziehen~
, um Bash davon abzuhalten, ihn in $ HOME zu erweitern. Was macht das#
in Ihrem Befehl?~
": Beachten Sie, wie ich Sachen zitiert habe. Denken Sie daran, immer Sachen zu zitieren! Und dies funktioniert nicht nur für magische Variablen: Jede Variable kann innerhalb von Bash ersetzt, die Länge der Zeichenfolge ermittelt und vieles mehr werden. Herzlichen Glückwunsch zum$PS1
schnellen Versuch : Sie könnten auch daran interessiert sein,$PROMPT_COMMAND
ob Sie sich in einer anderen Programmiersprache besser auskennen und eine kompilierte Eingabeaufforderung codieren möchten.echo "${PWD/#$HOME/~}"
ersetzt nicht meine$HOME
mit~
. Ersetzen~
durch\~
oder'~'
funktioniert. Alle diese Arbeiten an Bash 4.2.53 in einer anderen Distribution. Können Sie bitte Ihren Beitrag aktualisieren, um ihn~
für eine bessere Kompatibilität zu zitieren oder zu umgehen? Was ich mit meiner Frage "magische Variablen" meinte, war: Kann ich Bashs Variablensubstitution beispielsweise für die Ausgabe von verwenden,uname
ohne sie zuerst als Variable zu speichern? Was meine persönlichen$PROMPT_COMMAND
, ist es kompliziert .Wenn Sie morgen entscheiden, dass Sie Marry nicht lieben, kann sie auch ersetzt werden:
Es muss 50 Möglichkeiten geben, Ihren Geliebten zu verlassen.
quelle
Da kann ich keinen Kommentar hinzufügen. @ruaka Um das Beispiel besser lesbar zu machen, schreiben Sie es so
quelle
Reine POSIX - Shell - Methode, die im Gegensatz zu Roman Kazanovskyi ‚s
sed
-basierte Antwort keine externen Tools benötigt, nur um die eigene Mutter Shell Parameter Erweiterungen . Beachten Sie, dass lange Dateinamen minimiert werden, damit der Code besser in eine Zeile passt:Ausgabe:
Wie es funktioniert:
Kleinstes Suffixmuster entfernen.
"${f%$t*}"
gibt "I love
" zurück, wenn das Suffix$t
"Suzi*
" in$f
" " steht.I love
Suzi and Marry
Aber wenn
t=Zelda
, dann"${f%$t*}"
löscht nichts und gibt die gesamte Zeichenfolge "I love Suzi and Marry
" zurück.Dies wird zu Test verwendet , wenn
$t
in$f
mit[ "${f%$t*}" != "$f" ]
dem bewerten wird wahr , wenn die$f
Zeichenfolge „Suzi*
“ und falsch , wenn nicht.Wenn der Test true zurückgibt , erstellen Sie die gewünschte Zeichenfolge mit " Kleinstes Suffixmuster entfernen
${f%$t*}
"I love
"und" Kleinstes Präfixmuster entfernen${f#*$t}
"and Marry
", wobei die zweite Zeichenfolge$s
"Sara
" dazwischen liegt.quelle
Ich weiß, dass dies alt ist, aber da niemand über die Verwendung von awk gesprochen hat:
quelle
quelle