Odpowiedzi:
Użyj alternatywnego separatora wyrażeń regularnych, co sedpozwala na użycie dowolnego separatora (w tym znaków kontrolnych ):
sed "s~$var~replace~g" $file
$var
Czysta odpowiedź basha: użyj interpretacji parametrów, aby odwrócić ukośnik - uciec przed wszystkimi ukośnikami w zmiennej:
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
${parameter/pattern/string}. W tym przypadku parametr to var, wzorzec to /\/, a ciąg to \\/. Wszystkie wystąpienia wzorca są zastępowane, ponieważ wzór zaczyna się od /.
Użycie /w sedzie jako separatora spowoduje konflikt z ukośnikami w zmiennej podczas podstawiania, w wyniku czego pojawi się błąd. Jednym ze sposobów obejścia tego jest użycie innego ogranicznika, który jest unikalny dla wszystkich znaków znajdujących się w tej zmiennej.
var="/Users/Documents/name/file"
możesz użyć znaku octothorpe, który pasuje do okazji (lub dowolnego innego znaku, który nie jest /łatwy w użyciu)
sed "s#$var#replace#g"
lub
sed 's#$'$var'#replace#g'
jest to odpowiednie, gdy zmienna nie zawiera spacji
lub
sed 's#$"'$var'"#replace#g'
Rozsądniej jest skorzystać z powyższego, ponieważ jesteśmy zainteresowani zastąpieniem tego, co jest w tej zmiennej, tylko w porównaniu z podwójnym cudzysłowem całego polecenia, co może spowodować, że powłoka interpetuje dowolny znak, który może być uznany za specjalny znak powłoki.
$varzawiera ~, oczywiście będziesz musiał wybrać inny separator. Błąd „niezakończony” brzmi tak, jakby twój $varzawierał nową linię; możesz to naprawić, usuwając odwrotnym ukośnikiem każdą nową linię w wartości, ale nie sądzę, że jest to całkowicie przenośne. W zasadzie nie ma to związku z problemem cięć wartości.
sed -i "s~blah~$var~g" filez cudzysłowami tylko wokół właściwego sedskryptu.
To stare pytanie, ale żadna z odpowiedzi nie omawia operacji poza s/from/to/bardzo szczegółowymi informacjami.
Ogólna forma sedoświadczenia to
*address* *action*
gdzie adres może być zakresem wyrażenia regularnego lub zakresem numerów wierszy (lub pustym, w którym to przypadku akcja jest stosowana do każdego wiersza wejściowego). Na przykład
sed '1,4d' file
usunie linie od 1 do 4 ( adres to zakres numerów linii, 1,4a czynnością jest dpolecenie usunięcia); i
sed '/ick/,$s/foo/bar/' file
zastąpi pierwsze wystąpienie fooze barna każdej linii pomiędzy pierwszym meczu na regex icki końca pliku (the adres jest zasięg /ick/,$i działanie jest skomenda substytutems/foo/bar/ ).
W tym kontekście, jeśli ickpochodzi ze zmiennej, możesz to zrobić
sed "/$variable/,\$s/foo/bar/"
(zwróć uwagę na użycie podwójnych cudzysłowów zamiast pojedynczych, aby powłoka mogła interpolować zmienną i konieczność cytowania dosłownego znaku dolara wewnątrz podwójnych cudzysłowów), ale jeśli zmienna zawiera ukośnik, pojawi się błąd składniowy. (Powłoka rozwija zmienną, a następnie przekazuje wynikowy ciąg do sed; więc sedwidzi tylko tekst dosłowny - nie ma pojęcia o zmiennych powłoki).
Lekarstwem jest użycie innego separatora (gdzie oczywiście musisz mieć możliwość użycia znaku, który nie może występować w wartości zmiennej), ale w przeciwieństwie do s%foo%bar%przypadku, potrzebujesz również ukośnika odwrotnego przed separatorem, jeśli chcesz użyć innego separator niż domyślny /:
sed "\\%$variable%,\$s/foo/bar/" file
(w pojedynczych cudzysłowach wystarczyłby oczywiście pojedynczy lewy ukośnik); lub możesz osobno zmienić znaczenie każdego ukośnika w wartości. Ta konkretna składnia to tylko Bash:
sed "/${variable//\//\\/}/,\$s/foo/bar/" file
lub jeśli używasz innej powłoki, spróbuj
escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file
Dla jasności, gdyby $variablezawierał łańcuch, 1/2powyższe polecenia byłyby równoważne
sed '\%1/2%,$s/foo/bar/' file
w pierwszym przypadku i
sed '/1\/2/,$s/foo/bar/' file
w sekundę.
Użyj Perla, gdzie zmienne są obywatelami pierwszej klasy, a nie tylko rozwijaniem makr:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p czyta dane wejściowe wiersz po wierszu i drukuje wiersz po przetworzeniu\Qcytuje wszystkie metaznaki w następującym ciągu (nie są potrzebne dla wartości tutaj prezentowanej, ale konieczne, jeśli wartość zawierała [lub inne wartości specjalne dla regularnych wyrażeń)