Ich habe "Ich liebe Suzi und heirate" und ich möchte "Suzi" in "Sara" ändern.
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
Das Ergebnis muss folgendermaßen aussehen:
firstString="I love Sara and Marry"
Ich habe "Ich liebe Suzi und heirate" und ich möchte "Suzi" in "Sara" ändern.
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
Das Ergebnis muss folgendermaßen aussehen:
firstString="I love Sara and Marry"
Antworten:
Verwenden Sie Folgendes, um das erste Auftreten eines Musters durch eine bestimmte Zeichenfolge zu ersetzen :${parameter/pattern/string}
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"
# prints 'I love Sara and Marry'
Verwenden Sie zum Ersetzen aller Vorkommen Folgendes :${parameter//pattern/string}
message='The secret code is 12345'
echo "${message//[0-9]/X}"
# prints 'The secret code is XXXXX'
(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" .
\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 wollen STRING//
- ersetzen Sie alle - anstatt nur STRING/
.)
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:
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"
Für Dash funktionieren alle vorherigen Beiträge nicht
Die POSIX- sh
kompatible Lösung lautet:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
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:
sed "s/Suzi/$secondString/g" <<<"$firstString"
Es ist besser, bash zu verwenden, als sed
wenn 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/name
am Anfang ist. Wir brauchen nicht sed
!
Da bash gibt uns magische Variablen $PWD
und $HOME
kö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 $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 .
sed
den pwd
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:
today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt
Es muss 50 Möglichkeiten geben, Ihren Geliebten zu verlassen.
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}
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 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.
Ich weiß, dass dies alt ist, aber da niemand über die Verwendung von awk gesprochen hat:
firstString="I love Suzi and Marry"
echo $firstString | awk '{gsub("Suzi","Sara"); print}'
echo [string] | sed "s/[original]/[target]/g"