Jak przekazać zmienną zawierającą ukośniki jako wzorzec do sed
?
Na przykład, jeśli mam następującą zmienną:
var="/Users/Documents/name/file"
Chcę to przekazać sed
tak:
sed "s/$var/replace/g" "$file"
Jednak otrzymuję błędy. Jak mogę obejść ten problem?
$var
Czysta odpowiedź basha: użyj interpretacji parametrów, aby odwrócić ukośnik - uciec przed wszystkimi ukośnikami w zmiennej:
źródło
${parameter/pattern/string}
. W tym przypadku parametr tovar
, wzorzec to/\/
, a ciąg to\\/
. Wszystkie wystąpienia wzorca są zastępowane, ponieważ wzór zaczyna się od/
.Innym sposobem na zrobienie tego, chociaż brzydszym niż odpowiedź Anubhavy, jest uniknięcie wszystkich odwrotnych ukośników
var
za pomocą innegosed
polecenia:wtedy to zadziała:
źródło
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.możesz użyć znaku octothorpe, który pasuje do okazji (lub dowolnego innego znaku, który nie jest
/
łatwy w użyciu)lub
jest to odpowiednie, gdy zmienna nie zawiera spacji
lub
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.
źródło
$var
zawiera~
, oczywiście będziesz musiał wybrać inny separator. Błąd „niezakończony” brzmi tak, jakby twój$var
zawierał 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" file
z cudzysłowami tylko wokół właściwegosed
skryptu.To stare pytanie, ale żadna z odpowiedzi nie omawia operacji poza
s/from/to/
bardzo szczegółowymi informacjami.Ogólna forma
sed
oświadczenia togdzie 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
usunie linie od 1 do 4 ( adres to zakres numerów linii,
1,4
a czynnością jestd
polecenie usunięcia); izastąpi pierwsze wystąpienie
foo
zebar
na każdej linii pomiędzy pierwszym meczu na regexick
i końca pliku (the adres jest zasięg/ick/,$
i działanie jests
komenda substytutems/foo/bar/
).W tym kontekście, jeśli
ick
pochodzi ze zmiennej, możesz to zrobić(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ęcsed
widzi 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/
:(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:
lub jeśli używasz innej powłoki, spróbuj
Dla jasności, gdyby
$variable
zawierał łańcuch,1/2
powyższe polecenia byłyby równoważnew pierwszym przypadku i
w sekundę.
źródło
Użyj Perla, gdzie zmienne są obywatelami pierwszej klasy, a nie tylko rozwijaniem makr:
-p
czyta dane wejściowe wiersz po wierszu i drukuje wiersz po przetworzeniu\Q
cytuje 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ń)źródło