Weź następujący skrypt:
#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
Jeśli spróbuję uruchomić to w sh
( dash
tutaj), to się nie powiedzie z powodu nawiasów, które należy uciec. Ale nie muszę uciekać przed odwrotnymi ukośnikami (między oktetami lub w \s
lub \1
). Jaka jest tutaj reguła? A kiedy potrzebuję użyć {...}
lub [...]
? Czy jest lista tego, co robię i nie muszę uciekać?
shell-script
sed
quoting
obrzydliwie
źródło
źródło
function sedPath { path=$((echo $1|sed -r 's/([\$\.\*\/\[\\^])/\\\1/g'|sed 's/[]]/\[]]/g')>&1) } #Escape path for use with sed
Odpowiedzi:
Istnieją dwa poziomy interpretacji: skorupa i sed.
W powłoce wszystko między pojedynczymi cudzysłowami jest interpretowane dosłownie, z wyjątkiem samych pojedynczych cudzysłowów. Możesz efektywnie utworzyć pojedynczy cytat między pojedynczymi cytatami, pisząc
'\''
(zamknij pojedynczy cytat, jeden dosłowny pojedynczy cytat, otwórz pojedynczy cytat).Sed używa podstawowych wyrażeń regularnych . W BRE, aby traktować je dosłownie, znaki
$.*[\^
należy cytować, poprzedzając je odwrotnym ukośnikiem, z wyjątkiem wewnętrznych zestawów znaków ([…]
). Litery, cyfry i(){}+?|
nie mogą być cytowane (możesz uciec od cytowania niektórych z nich w niektórych implementacjach). Sekwencje\(
,\)
,\n
, aw niektórych implementacjach\{
,\}
,\+
,\?
,\|
i inne backslash + alfanumeryczne mają specjalne znaczenie. Możesz uciec od nie cytowania$^
niektórych pozycji w niektórych implementacjach.Ponadto przed odwrotnym użyciem
/
wyrażeń regularnych potrzebujesz odwrotnego ukośnika . Możesz wybrać alternatywny znak jako separator, pisząc np.s~/dir~/replacement~
Lub\~/dir~p
; będziesz potrzebować odwrotnego ukośnika przed separatorem, jeśli chcesz uwzględnić go w BRE. Jeśli wybierzesz postać, która ma specjalne znaczenie w BRE i chcesz ją dosłownie uwzględnić, potrzebujesz trzech odwrotnych ukośników; Nie polecam tego, ponieważ może zachowywać się inaczej w niektórych implementacjach.W skrócie, dla
sed 's/…/…/'
:'\''
aby skończyć z jednym cytatem w wyrażeniu regularnym.$.*/[\]^
i tylko te znaki (ale nie wewnątrz wyrażeń w nawiasach). (Technicznie nie należy wprowadzić odwrotny ukośnik przed]
ale nie wiem od implementacji, że traktuje]
i\]
różnie poza wyrażeń nawiasów).-
aby być traktowanym dosłownie, upewnij się, że jest ono pierwsze lub ostatnie ([abc-]
lub[-abc]
nie).[a-bc]
^
aby być traktowanym dosłownie, upewnij się, że nie jest ono pierwsze (użyj[abc^]
, nie).[^abc]
]
do listy znaków pasujących do wyrażenia^
w nawiasach, ustaw go jako pierwszy znak (lub pierwszy po nim dla zestawu negacji):[]abc]
lub[^]abc]
(nie).[abc]]
ani[abc\]]
W tekście zastępczym:
&
i\
należy je cytować, poprzedzając je odwrotnym ukośnikiem, podobnie jak separator (zwykle/
) i znaki nowej linii.\
po którym następuje cyfra ma specjalne znaczenie.\
po której następuje litera ma specjalne znaczenie (znaki specjalne) w niektórych implementacjach, a\
po niej inne znaki\c
lub wc
zależności od implementacji.sed 's/…/…/'
), użyj,'\''
aby wstawić pojedynczy cytat w tekście zastępczym.Jeśli wyrażenie regularne lub tekst zastępczy pochodzi ze zmiennej powłoki, pamiętaj o tym
\n
(która nigdy nie będzie pasować, chyba że masz innysed
kod dodający znaki nowej linii do obszaru szyku). Należy jednak pamiętać, że w niektórychsed
implementacjach nie będzie działał w wyrażeniach nawiasów .&
,\
i nowe linie muszą być cytowane.sed -e "s/$BRE/$REPL/"
.źródło
\\*
). Przykład:echo "***NEW***" | sed /\\*\\*\\*NEW\\*\\*\\*/s/^/#/
Problem, którego doświadczasz, nie wynika z interpolacji powłoki i ucieczki - to dlatego, że próbujesz użyć rozszerzonej składni wyrażeń regularnych bez podania opcji
-r
lub--regexp-extended
.Zmień linię sed z
do
i będzie działać tak, jak wierzę, że masz zamiar.
Domyślnie sed używa podstawowych wyrażeń regularnych (styl grep), które wymagałyby następującej składni:
źródło
-r
jako opcji było w moim przypadku konieczne.O ile nie chcesz interpolować zmiennej powłoki w wyrażeniu sed, użyj pojedynczych cudzysłowów dla całego wyrażenia, ponieważ powodują one interpretację wszystkiego między nimi, w tym odwrotnych ukośników.
Więc jeśli chcesz, aby sed zobaczył
s/\(127\.0\.1\.1\)\s/\1/
umieszczanie pojedynczych cudzysłowów wokół niego, a powłoka nie dotknie nawiasów ani odwrotnych ukośników. Jeśli potrzebujesz interpolować zmienną powłoki, umieść tylko tę część w podwójnych cudzysłowach. Na przykładPozwoli to zaoszczędzić kłopotu z zapamiętywaniem, które metaznaki powłoki nie są poprzedzane podwójnymi cudzysłowami.
źródło
sed
to zobaczyćs/(127\.0\.1\.1)/...
, ale umieszczenie tego w skrypcie powłoki w obecnej postaci nie działa. To, co mówisz o powłoce nie dotykającej nawiasów, wydaje się błędne. Zredagowałem moje pytanie, aby je rozwinąć.sed 's/(127\.0\.1\.1)/IP \1/'
kończy się niepowodzeniem, ponieważ sed musi zobaczyć\(
i\)
dla składni grupy,(
a nie i)
.