sed: substitua strings por conteúdo variável

3

Estou tentando escrever um script que encontre strings em um determinado padrão ( {?varname} ) e as substitua por uma variável de ambiente correspondente.

Isso é o que eu tenho até agora:

function get_env() {
   var=$1
   echo ${!var}
}

sed -e 's/{?\([a-z]*}\)/'$(get_env '')'/g' file.txt

A função funciona, por ex. get_env LOGNAME - > dotan

Sed retorna o valor da função, e. se eu substituir o conteúdo da função por echo __$1__ , receberei {?logname} - > __LOGNAME__

No entanto, juntos não funciona. É como se a função sempre retornasse uma string vazia.

Não sei o que causa o problema aqui. Alguma idéia?

    
por Dotan 25.02.2018 / 13:46

2 respostas

5

Essa linha de comando executaria get_env '' em uma substituição de comando e colaria sua saída na linha de comando de sed . Provavelmente, você deve receber um erro sobre isso, pois não é um nome válido para uma variável.

Você poderia usar Perl e s/\{\?([a-z]+)\}/$ENV{$1}/ para fazer isso; %ENV é um hash que contém as variáveis de ambiente:

$ export name=you
$ echo "hello {?name}" | perl -pe 's/\{\?([a-z]+)\}/$ENV{$1}/'
hello you

(o GNU sed tem o comando e para rodar programas externos, mas ele usa todo o espaço padrão, não apenas a parte correspondente, então não parece se encaixar muito bem aqui.)

Puramente no Bash, se você insistir ( setvar.sh ):

#!/bin/bash
while IFS= read -r line ; do
        while [[ $line =~ ^(.*)(\{\?[a-zA-Z0-9_]+\})(.*)$ ]] ; do
                varname=${BASH_REMATCH[2]}
                varname=${varname#"{?"}
                varname=${varname%\}}
                printf -v line "%s%s%s" "${BASH_REMATCH[1]}" "${!varname}" "${BASH_REMATCH[3]}"
        done
        printf "%s\n" "$line" 
done < "${1-/dev/stdin}"

$ echo 'foo {?BASH_VERSION} {?blah} bar' |blah=ABC bash setvar.sh
foo 4.4.12(1)-release ABC bar
    
por 25.02.2018 / 14:29
1

Esta é a solução que eu criei

grep -o '{?\S*}' file.txt | sed 's/{?\(.*\)}//' | xargs -I {} sh -c "sed -i -e 's/{?"{}"}/'$"{}"'/' file.txt"

Para dividir:

  • grep -o '{?\S*}' file.txt - obtém todas as variáveis para substituir
  • sed 's/{?\(.*\)}//' - tira a formatação
  • xargs -I {} sh -c "sed -i -e 's/{?"{}"}/'$"{}"'/' file.txt" - pesquise e substitua por cada variável
por 26.02.2018 / 19:20

Tags