Reescreva um comando find que use sed -i para o AIX

1

Eu tenho um script que procura por uma string e a substitui por meio do comando sed. Se essa string contiver caracteres especiais, o script irá escapar deles (exceto para a barra porque é meu delimitador atual para sed e a coluna porque marca a string na linha bash).

Aqui vai:

raw_searchstring='SearchForThis';
raw_replacementstring='ReplaceWithThis';

#Escape special characters:
quoted_searchstring=$(printf %s "$raw_searchstring" | sed 's/[][()\.^$?*+]/\&/g');
quoted_replacementstring=$(printf %s "$raw_replacementstring" | sed 's/[][()\.^$?*+]/\&/g');

find ./ -type f -exec sed -i -r "s/$quoted_searchstring/$quoted_replacementstring/" {} \;

Eu testei isso no Ubuntu e funcionou muito bem.

No entanto, preciso executar o script em um sistema AIX. Como ele não suporta edição sequencial com sed -i, tentei o seguinte, como sugerido em uma pergunta semelhante aqui ( Edição de sed-in do AIX ):

find ./ -type f -exec sed -r 's/$quoted_searchstring/$quoted_replacementstring/' infile > tmp.$$ && mv tmp.$$ infile {} \;

Aqui é onde eu recebo o erro

find: missing argument to '-exec'

então tentei passar mais de uma instrução -exec para find com esta linha:

find /home/tobias/Desktop -type f -exec sed -r 's/$quoted_searchstring/$quoted_replacementstring/' infile > tmp.$$ {} \; -exec mv tmp.$$ infile {} \;

que não funciona:

sed: can't read infile: No such file or directory

Não tenho certeza do que fiz de errado. Você pode me ajudar a corrigir essa linha de código ou me apontar na direção certa?

    
por Rich B. Goodman 20.04.2016 / 16:54

1 resposta

2

Suas tentativas não estão funcionando porque você está tentando usar operadores de shell como && e > no comando executado por find , mas você está digitando esses operadores diretamente no comando, então eles é executado pelo shell que está chamando find . Seus comandos são analisados como

find … > tmp.$$ && mv …

por exemplo. a primeira invocação find é

find ./ -type f -exec sed 's/$quoted_searchstring/$quoted_replacementstring/' infile

com saída redirecionada para tmp.$$ . Há outros problemas com o comando: infile deve ser {} (é o arquivo que find encontrou), e as aspas simples ao redor da expressão sed devem ser aspas duplas, já que você está usando variáveis shell lá. / p>

Como você precisa usar construções de shell no comando executado por find , informe find para executar um shell.

find … -exec sh -c '…' {} \;

Para evitar dificuldades de citação, passe as coisas que precisam ser citadas, como a expressão sed, como argumentos para sh .

find ./ -type f -exec sh -c '
    sed "$0" "$1" >"$1.new" && mv "$1.new" "$1"
  ' "s/$quoted_searchstring/$quoted_replacementstring/" {} \;

Para um pequeno ganho de desempenho com uma leve perda de legibilidade, você pode usar o formulário -exec … {} + e um loop de shell.

find ./ -type f -exec sh -c '
    for x; do
      sed "$0" "$x" >"$x.new" && mv "$x.new" "$x";
    done
  ' "s/$quoted_searchstring/$quoted_replacementstring/" {} +

Como alternativa, se a versão de ksh93 em seu AIX não for muito antiga, você poderá usar seu recurso de globalização recursiva (introduzido no ksh93p).

set -G
for x in **; do
  [[ -f $x ]] || continue
  sed "s/$quoted_searchstring/$quoted_replacementstring/" "$x" >"$x.new" && mv "$x.new" "$x";
done

Em qualquer caso, observe que você também precisará ajustar sua conversão de string para regexp para produzir uma expressão regular básica, pois o sinalizador -r para usar ERE é uma extensão GNU. Além disso, seu código existente tem alguns bugs: você esqueceu de citar barras e não está citando os caracteres certos no texto de substituição.

quoted_searchstring=$(printf %s "$raw_searchstring" | sed 's![[\/.^$*]!\&!g');
quoted_replacementstring=$(printf %s "$raw_replacementstring" | sed -e 's![][\/&]!\&!g' -e '!$ s!$!\!');
    
por 21.04.2016 / 00:44