Para lidar de forma robusta com informações variáveis em expressões regulares, você precisa escapar dos metacaracteres da expressão regular. Esta pergunta foi respondida muitas vezes - eu fiz pessoalmente muitas vezes - mas aqui está o básico:
^$*[]\.
^ Esses são metacaracteres de expressão regular básica. Cada um deles tem um significado especial em uma expressão regular como sintaxe e não são interpretados literalmente. O significado de vários deles é, na verdade, dependente da posição e, por isso, às vezes may consegue incluí-los em uma expressão regular sem o escape adequado, mas isso não significa que você deveria - especialmente quando a expressão regular é construída de entrada não validada.
Mas tem mais:
delimiter newline &
^ Esses são caracteres de sintaxe de substituição sed s/// ubstitution. O delimitador - que é tradicionalmente / - é variável e sed interpretará automaticamente como o primeiro caractere após um s para um novo comando.
A nova linha - no lado esquerdo da expressão regular da declaração - é positivamente inescapável. É inválido lá. A única maneira de substituir uma nova linha é usar o \n escape - mas a única maneira de obter uma nova linha no espaço padrão que pode ser encontrada em uma expressão regular é colocar uma lá você mesmo - e então isso geralmente não é um problema. No lado direito da s/// ubstitution - o lado replace - a nova linha é passível de escape - como todo o resto - com \ , que é o metacaractere de escape. O mesmo é verdade para & .
E para criar um script robusto de sed de variáveis, você precisa escapar dele. Esse é o único caminho. Alterar o delimitador porque você espera que haja um em sua instrução não é um método robusto. Você valida entrada e descarta qualquer chance de erros de sintaxe, ou você evita caracteres de sintaxe para indicar o que pretende. Essas são as duas maneiras de escrever programas robustos - não há outros.
Felizmente, sed torna isso muito fácil. Como mencionado - a barra invertida \ é o metacaractere de escape e até escapará quando for duplicada. E assim podemos usar sed para escapar de sed .
printf %s\n "$regex_field" "$replace_field" |
sed -ne'h;n' -e's|[\&/]|\&|g' \
-ex -e's|[]/\.$^*[]|\&|g' \
-eG -e's|\(.*\)\n\(.*\)|s///|p' |
sed -f- edit_file
Veja? A entrada é separada em novas linhas e, portanto, conforme escrita, não é permitida uma nova linha em $regex_field ou $replace_field . Você poderia lidar com isso também, mas isso não acontece e a expectativa é que a entrada seja validada para descartá-la.
Em qualquer caso, as linhas de entrada são alimentadas com o primeiro sed em pares e h olds uma cópia da primeira metade de cada par de linhas e pula n ext para o segundo, quando ele escapa os caracteres relevantes para o lado direito de uma declaração sed s/// ubstitution. Em seguida, e x altera seus espaços de retenção e padrão e escapa para o lado esquerdo, antes de G etting o RHS anexado ao LHS como separado por um delimitador \n ewline. A última coisa que tem que fazer é adicionar os s/// bits antes de p rinting o comando escapado para o padrão.
O segundo sed lê seu arquivo de script em - (que geralmente é interpretado como padrão, mas você pode querer tentar /dev/fd/0 se não) e então aplica isso script para o seu nome edit_file .