Procura e substitui múltiplas strings em um script usando comandos vim (search and replace) sem sed?

1

Um script que cria um arquivo para a precipitação climática é

#!/bin/ksh

x=10
b=snow
c=rain
d=snow
e=hail
echo "$x,$b,$c,$d,$e" > weatherfile

exit 0

dado

3,8s/snow/dry/g

Para a pesquisa e substituição, qual é a melhor maneira de implementar isso em um script?

Da perspectiva do comando, sed seria necessário?

Meus pensamentos são de que o seguinte deve funcionar:

sed 3,8s/snow/dry/g weatherfile

Mas e se sed não puder ser usado? Eu precisaria abrir e fechar o arquivo e alguma forma de como executar

:3,8s/snow/dry/g enquanto o arquivo está aberto? Como isso pode ser implementado?

    
por Juan Davila 07.05.2015 / 21:21

2 respostas

2

Você pode usar os comandos vim diretamente com um documento aqui (que é especialmente útil para substituições irregulares):

#!/bin/ksh
vim weatherfile <<EOF
:3,8s/snow/dry/g
:wq
EOF
    
por 07.05.2015 / 22:43
0

Você pode fazer isso inteiramente no shell com um script como este:

#!/bin/bash
line_num=0
while IFS= read -r line
do
        : $((line_num++))
        if [[ line_num -ge 3  &&  line_num -le 8 ]]
        then
                printf "%s\n" "${line/snow/dry}"
        else
                printf "%s\n" "$line"
        fi
done

(eu testei isso em bash, e relatórios Andrey que funciona em ksh mas não funcionará em todas as versões compatíveis com POSIX de sh .) Ele lê linhas da entrada padrão. Conta linhas (com line_num=0 e : $((line_num++)) porque você deseja especificar um intervalo de números de linha; se esse requisito for removido, as instruções referenciando line_num podem ser excluídas. O teste condicional

        if [[ line_num -ge 3  &&  line_num -le 8 ]]

significa “IF (line_num ≥ 3) AND (line_num ≤ 8)”, correspondendo ao intervalo 3,8 , isto é, 3 a 8. (Que é um ponto de confusão para iniciantes Unix, quem espera que 3,8 signifique "3 e também 8", e espera que "3 a 8" seja representado como 3-8 - isto é, a convenção usada pelas caixas de diálogo de impressão no Windows para imprimir um subconjunto das páginas de um documento.)

Nas linhas que estão no intervalo, ele usa o

        ${parameter/pattern/string)

forma de expansão de parâmetro para substituir "neve" por "seco" antes de gravar a linha na saída padrão. Linhas fora do intervalo são escritas sem modificações.

Isso mudará a primeira ocorrência (se houver) de "neve" em cada linha dentro do alcance. Para substituir todas as ocorrências, use ${line//snow/dry} (insira um / extra antes da "neve").

Não estou claro sobre o quadro geral do que você quer.

  • Você pode incorporar o código acima em seu script existente.
  • Se você modificou seu script (vamos chamá-lo de weather.sh ) escrever para stdout em vez do arquivo, então você poderia dizer

    ./weather.sh | ./do_substitute.sh > weatherfile
    
  • Se você quiser criar weatherfile da mesma maneira que está fazendo agora, mas depois mudá-lo depois, você poderia fazer

    ./do_substitute.sh < weatherfile > weatherfile.tmp
    mv weatherfile.tmp weatherfile
    
por 08.05.2015 / 07:07