Ersetzen Sie eine Zeichenfolge im Shell-Skript durch eine Variable


92

Ich verwende den folgenden Code zum Ersetzen einer Zeichenfolge in einem Shell-Skript.

echo $LINE | sed -e 's/12345678/"$replace"/g'

Es wird jedoch durch $replaceanstelle des Werts dieser Variablen ersetzt.

Kann jemand sagen, was schief gelaufen ist?


Die häufig gestellte Frage zum Umgang mit Werten mit Schrägstrichen finden Sie unter stackoverflow.com/questions/5864146/use-slashes-in-sed-replace
Tripleee

Antworten:


142

Wenn Sie interpretieren möchten $replace, sollten Sie keine einfachen Anführungszeichen verwenden, da diese das Ersetzen von Variablen verhindern.

Versuchen:

echo $LINE | sed -e "s/12345678/\"${replace}\"/g"

Angenommen, Sie möchten die Anführungszeichen eingeben. Wenn Sie die Anführungszeichen nicht möchten, verwenden Sie:

echo $LINE | sed -e "s/12345678/${replace}/g"

Transkript:

pax> export replace=987654321
pax> echo X123456789X | sed "s/123456789/${replace}/"
X987654321X
pax> _

Achten Sie nur darauf, dass ${replace}keine Zeichen von Bedeutung sind sed(wie /zum Beispiel), da dies zu Verwirrung führen kann, wenn Sie nicht entkommen. Aber wenn Sie, wie Sie sagen, eine Nummer durch eine andere ersetzen, sollte das kein Problem sein.


Ich möchte nicht, dass die Anführungszeichen eingegeben werden. Ich möchte, dass eine Zahl durch eine andere ersetzt wird
Vijay

1
paxdiablo: setist auch nicht nötig (und wie wolltest du es überhaupt benutzen?). Einfach replace=987654321.
Roman Cheplyaka

Normalerweise verwende ich immer, exportum sicherzustellen, dass Variablen für Kinder festgelegt sind, aber wie Sie sagen, können Sie dies genauso gut vermeiden. Die Verwendung oder Nichtverwendung von exportist hier jedoch irrelevant (ein Stilproblem) und hat keine Auswirkung auf die tatsächliche Antwort, dh wie Variablen innerhalb eines sedBefehls verwendet werden.
Paxdiablo

Diese Lösung scheint mit der -iOption nicht zu funktionieren . Würdest du wissen warum? oder wie soll es funktionieren?
Gabriel

1
Vielleicht weisen Sie auch darauf hin, dass für den Wechsel von einfachen zu doppelten Anführungszeichen ein $oder `im sedSkript mit einem Backslash maskiert werden muss, um es vor dem Substitutionsmechanismus der Shell für Zeichenfolgen in doppelten Anführungszeichen zu schützen.
Tripleee

73

Sie können die Shell (bash / ksh) verwenden.

$ var="12345678abc"
$ replace="test"
$ echo ${var//12345678/$replace}
testabc

3
Vielleicht möchten Sie erwähnen, dass dies bash-spezifisch ist (und ksh?). Wahrscheinlich nicht von Bedeutung für die meisten Menschen, aber einige von uns sind immer noch gezwungen, an alten UNIXen zu arbeiten :-)
paxdiablo

6
/bin/shBeachten Sie, dass dies auch bei Dash fehlschlägt, was bei vielen modernen Linuxes der Fall ist.
Phihag

26

Nicht spezifisch für die Frage, aber für Leute, die die gleiche Funktionalität benötigen, die aus Gründen der Klarheit gegenüber früheren Antworten erweitert wurde:

# create some variables
str="someFileName.foo"
find=".foo"
replace=".bar"
# notice the the str isn't prefixed with $
#    this is just how this feature works :/
result=${str//$find/$replace}
echo $result    
# result is: someFileName.bar

str="someFileName.sally"
find=".foo"
replace=".bar"
result=${str//$find/$replace}
echo $result    
# result is: someFileName.sally because ".foo" was not found

8

Einfache Anführungszeichen sind sehr stark. Sobald Sie drinnen sind, können Sie nichts mehr tun, um die Variablensubstitution aufzurufen, bis Sie gehen. Verwenden Sie stattdessen doppelte Anführungszeichen:

echo $LINE | sed -e "s/12345678/$replace/g"


4
echo $LINE | sed -e 's/12345678/'$replace'/g'

Sie können weiterhin einfache Anführungszeichen verwenden, müssen diese jedoch "öffnen", wenn die Variable an der richtigen Stelle erweitert werden soll. Andernfalls wird die Zeichenfolge "wörtlich" genommen (wie @paxdiablo richtig angegeben hat, ist auch seine Antwort richtig).


Dies hat das Problem, dass die Verwendung $replaceaußerhalb von Anführungszeichen dazu führt, dass die Shell eine Whitespace-Tokenisierung und eine Platzhaltererweiterung für den Wert durchführt. Dies scheint mit einfachen Werten zu funktionieren, kann jedoch bei nicht trivialen Zeichenfolgen dramatisch explodieren. Verwenden Sie dies nicht im Produktionscode.
Tripleee

2

Damit Ihre Shell die Variable erweitern kann, müssen Sie doppelte Anführungszeichen wie verwenden

sed -i "s#12345678#$replace#g" file.txt

Dies wird unterbrochen, wenn $replaceSonderzeichen sed( #, \) enthalten sind. Sie können sie jedoch vorverarbeiten $replace, um sie zu zitieren:

replace_quoted=$(printf '%s' "$replace" | sed 's/[#\]/\\\0/g')
sed -i "s#12345678#$replace_quoted#g" file.txt

0

Ich hatte eine ähnliche Anforderung, aber mein Ersatz-Var enthielt ein kaufmännisches Und. Wenn ich dem kaufmännischen Und so entkommen konnte, löste sich mein Problem:

replace="salt & pepper"
echo "pass the salt" | sed "s/salt/${replace/&/\&}/g"

-1

Verwenden Sie dies stattdessen

echo $LINE | sed -e 's/12345678/$replace/g'

Das funktioniert bei mir einfach die Anführungszeichen entfernen


-2

Ich bevorzuge doppelte Anführungszeichen, da einfache Quptes sehr mächtig sind, da wir sie verwenden, wenn sie nichts darin ändern oder die variable Substitution aufrufen können.

Verwenden Sie daher doppelte Anführungszeichen.

echo $LINE | sed -e "s/12345678/$replace/g"

6
Unterscheidet sich das von Daves Antwort ?
devnull
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.