Pegue o seguinte script:
#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
Se eu tentar executar isso em sh
( dash
aqui), ele falhará por causa dos parênteses, que precisam ser escapados. Mas não preciso escapar das barras invertidas (entre os octetos, ou no \s
ou \1
). Qual é a regra aqui? E quando eu preciso usar {...}
ou [...]
? Existe uma lista do que faço e não preciso escapar?
shell-script
sed
quoting
detly
fonte
fonte
function sedPath { path=$((echo $1|sed -r 's/([\$\.\*\/\[\\^])/\\\1/g'|sed 's/[]]/\[]]/g')>&1) } #Escape path for use with sed
Respostas:
Existem dois níveis de interpretação aqui: a concha e sed.
No shell, tudo entre aspas simples é interpretado literalmente, exceto as próprias aspas. Você pode efetivamente ter uma única citação entre aspas simples, escrevendo
'\''
(aspas simples fechadas, uma aspas simples literal, aspas simples abertas).Sed usa expressões regulares básicas . Em um BRE, para que eles sejam tratados literalmente, os caracteres
$.*[\^
precisam ser citados precedendo-os por uma barra invertida, exceto dentro dos conjuntos de caracteres ([…]
). Letras, dígitos e(){}+?|
não devem ser citados (você pode citar alguns deles em algumas implementações). As sequências\(
,\)
,\n
, e em algumas implementações\{
,\}
,\+
,\?
,\|
e outra barra invertida + alfanuméricos têm significados especiais. Você pode evitar não citar$^
em algumas posições em algumas implementações.Além disso, você precisa de uma barra invertida antes
/
para aparecer na regex fora das expressões entre colchetes. Você pode escolher um caractere alternativo como delimitador escrevendo, por exemplo,s~/dir~/replacement~
ou\~/dir~p
; você precisará de uma barra invertida antes do delimitador, se desejar incluí-lo no BRE. Se você escolher um personagem que tenha um significado especial em um BRE e desejar incluí-lo literalmente, precisará de três barras invertidas; Eu não recomendo isso, pois pode se comportar de maneira diferente em algumas implementações.Em poucas palavras, para
sed 's/…/…/'
:'\''
para terminar com uma citação única na regex.$.*/[\]^
e somente esses caracteres (mas não dentro das expressões entre colchetes). (Tecnicamente, você não deve colocar uma barra invertida antes,]
mas eu não conheço uma implementação que trate]
e\]
diferentemente das expressões entre colchetes.)-
ser tratada literalmente, verifique se é a primeira ou a última ([abc-]
ou[-abc]
não).[a-bc]
^
ser tratado literalmente, ter certeza que é não primeiro (uso[abc^]
, não).[^abc]
]
na lista de caracteres correspondidos por uma expressão entre colchetes, torne-o o primeiro caractere (ou o primeiro depois^
de um conjunto negado):[]abc]
ou[^]abc]
(não).[abc]]
nem[abc\]]
No texto de substituição:
&
e\
precisam ser citados precedendo-os por uma barra invertida, assim como o delimitador (geralmente/
) e as novas linhas.\
seguido por um dígito tem um significado especial.\
seguido por uma letra tem um significado especial (caracteres especiais) em algumas implementações e\
seguido por algum outro meio de caractere\c
ouc
dependendo da implementação.sed 's/…/…/'
), use'\''
para colocar uma aspas simples no texto de substituição.Se o regex ou o texto de substituição vier de uma variável do shell, lembre-se de que
\n
(que nunca corresponderá, a menos que você tenha outrosed
código adicionando caracteres de nova linha ao espaço do padrão). Mas observe que ele não funcionará dentro das expressões de colchete em algumassed
implementações.&
,\
e novas linhas precisam ser citado.sed -e "s/$BRE/$REPL/"
.fonte
\\*
). Exemplo:echo "***NEW***" | sed /\\*\\*\\*NEW\\*\\*\\*/s/^/#/
O problema que você está enfrentando não se deve à interpolação e escape do shell - é porque você está tentando usar a sintaxe de expressão regular estendida sem passar pela opção
-r
ou--regexp-extended
.Mude sua linha sed de
para
e funcionará como acredito que você pretende.
Por padrão, o sed usa expressões básicas regulares (pense no estilo grep), o que exigiria a seguinte sintaxe:
fonte
-r
como opção foi o necessário no meu caso.A menos que você queira interpolar uma variável de shell na expressão sed, use aspas simples para toda a expressão porque elas fazem com que tudo entre elas seja interpretado como está, incluindo barras invertidas.
Portanto, se você deseja que o sed veja
s/\(127\.0\.1\.1\)\s/\1/
aspas simples, o shell não tocará nos parênteses ou nas barras invertidas. Se você precisar interpolar uma variável de shell, coloque apenas essa parte entre aspas duplas. Por exemploIsso evitará que você lembre quais metacaracteres do shell não são escapados por aspas duplas.
fonte
sed
vers/(127\.0\.1\.1)/...
, mas colocar isso em um script de shell como está não funciona. O que você está dizendo sobre o shell não tocar nos parênteses parece errado. Eu editei minha pergunta para elaborar.sed 's/(127\.0\.1\.1)/IP \1/'
falha porque o sed precisa ver\(
e\)
para a sintaxe do grupo, não(
e)
.