Preciso poder exportar algumas variáveis de um arquivo, para poder usá-lo em meu script BASH. o conteúdo do arquivo é mais ou menos assim:
my.variable.var1=a-long-ling.with.lot_of_different:characters:and_numbers
my.variable.another.var2=another-long-ling.with.lot_of_different:characters:and_numbers
my.variable.number3=yet_another_long-ling.with.lot_of_different:characters:and_numbers
Primeiro tentei obtê-lo usando source
como estão e recebi a mensagem de erro dizendo: command not found
. Tentei usar export
, o que me deu uma mensagem de erro dizendo: not a valid identifier
.
Acho que só consigo exportar se mudar minha variável de my.variable.var1
para my_variable_var1
.
Consigo fazer isso cortando a linha em =
e substituindo todos .
s por _
s e adicionando as variáveis novamente.
Então minha pergunta é: é possível mudar:
my.variable.var1=a-long-ling.with.lot_of_different:characters:and_numbers
my.variable.another.var2=another-long-ling.with.lot_of_different:characters:and_numbers
my.variable.number3=yet_another_long-ling.with.lot_of_different:characters:and_numbers
para
my_variable_var1=a-long-ling.with.lot_of_different:characters:and_numbers
my_variable_another_var2=another-long-ling.with.lot_of_different:characters:and_numbers
my_variable_number3=yet_another_long-ling.with.lot_of_different:characters:and_numbers
usando algum daqueles 'one liners' legais? Adoraria usar isso, além de um bom aprendizado.
Responder1
Com sed
:
sed -e :1 -e 's/^\([^=]*\)\./\1_/;t1'
Isso é substituir uma sequência de caracteres diferente .
do início da linha seguida .
pela mesma sequência e _
e repetir o processo até que não corresponda mais.
Com awk
:
awk -F = -v OFS== '{gsub(/\./, "_", $1); print}'
Agora, caso o lado direito =
contenha caracteres especiais para o shell ( \
"$&();'#~<>...`, espaço, tabulação, outros espaços em branco...), você pode querer citá-lo :
sed "s/'/'\\\\''/g;:1"'
s/^\([^=]*\)\./\1_/;t1'"
s/=/='/;s/\$/'/"
Ou:
awk -F = -v q="'" -v OFS== '
{gsub(q, q "\\" q q)
gsub(/\./, "_", $1)
$2 = q $2
print $0 q}'
Responder2
Usando bash
:
while IFS='=' read -r i j; do echo "${i//./_}=$j" ; done
Usamos o padrão de expansão de parâmetros ${i//./_}
para substituir todos .
os s por _
s no nome da variável.
Exemplo:
$ cat file.txt
my.variable.var1=a-long-ling.with.lot_of_different:characters:and_numbers
my.variable.another.var2=another-long-ling.with.lot_of_different:characters:and_numbers
my.variable.number3=yet_another_long-ling.with.lot_of_different:characters:and_numbers
$ while IFS='=' read -r i j; do echo "${i//./_}=$j" ; done <file.txt
my_variable_var1=a-long-ling.with.lot_of_different:characters:and_numbers
my_variable_another_var2=another-long-ling.with.lot_of_different:characters:and_numbers
my_variable_number3=yet_another_long-ling.with.lot_of_different:characters:and_numbers
Responder3
Aqui está outro sed
:
sed 'h;s/\./_/g;G;s/=.*=/=/'
Este faz apenas duas substituições, independentemente do número de pontos anteriores ao =
so com uma entrada como:
my.var.an.other.var.with.many.dots=line.with.many:chars:and_numbers.and.stuff
o resultado é
my_var_an_other_var_with_many_dots=line.with.many:chars:and_numbers.and.stuff
Isso funciona bem quando há um =
caractere por linha (como na sua entrada de exemplo).
Uma abordagem mais genérica que sempre substitui apenas o primeiro =
(e somente se a linha contiver pelo menos um =
), mesmo se houver vários =
caracteres por linha:
sed '/=/{ # if line matches =
h # copy pattern space over the hold space
s/\./_/g # replace all . with =
G # append hold space content to pattern space
s/=.*\n[^=]*=/=/ # replace from the first = up to the first = after
}' # the newline character with a single =
ou
sed -e '/=/{h;s/\./_/g;G;s/=.*\n[^=]*=/=/' -e '}'
então com uma entrada como:
my.var.with.many.dots.but.no.equal.sign.and.stuff
my.var.with.many.dots=line.with.many:chars:numbers_and.stuff
other.var.with.many.dots=and.with.more.than=one.equal.sign=and.stuff
ele produz:
my.var.with.many.dots.but.no.equal.sign.and.stuff
my_var_with_many_dots=line.with.many:chars:numbers_and.stuff
other_var_with_many_dots=and.with.more.than=one.equal.sign=and.stuff