Substitua todas as ocorrências de um caractere se ocorrer antes de outro caractere

2

Eu preciso poder exportar algumas variáveis de um arquivo, para que eu possa usá-lo no meu script BASH. o conteúdo do arquivo é algo 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 fazer o sourcing usando source como estão e recebi a mensagem de erro dizendo: command not found . Eu tentei usar export , o que me deu uma mensagem de erro dizendo: not a valid identifier .

Acho que só posso exportar se alterar minha variável de my.variable.var1 para my_variable_var1 .
Eu posso fazer isso cortando a linha em = e então substituindo todo . s por _ s e adicionando as variáveis de volta.

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 qualquer um desses cool 'one liners'? Adoraria usar isso, além de um bom aprendizado.

    
por AbhinavK 05.11.2015 / 11:28

3 respostas

1

com sed :

sed -e :1 -e 's/^\([^=]*\)\./_/;t1'

Isso substitui uma sequência de caracteres diferente de . no início da linha, seguida por . pela mesma sequência e _ , e repita o processo até que não seja mais correspondente.

com awk :

awk -F = -v OFS== '{gsub(/\./, "_", $1); print}'

Agora, caso o lado direito do = contenha caracteres especiais para o shell ( \ "$ & (); '# ~ < > ...', espaço, tabulação, outro espaços em branco ...), você pode citar:

sed "s/'/'\\''/g;:1"'
     s/^\([^=]*\)\./_/;t1'"
     s/=/='/;s/\$/'/"

Ou:

awk -F = -v q="'" -v OFS== '
   {gsub(q, q "\" q q)
    gsub(/\./, "_", $1)
    $2 = q $2
    print $0 q}'
    
por 05.11.2015 / 11:33
0

Usando bash :

while IFS='=' read -r i j; do echo "${i//./_}=$j" ; done

Usamos o padrão de expansão de parâmetro ${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
    
por 05.11.2015 / 11:36
0

Aqui está outro sed :

sed 'h;s/\./_/g;G;s/=.*=/=/'

Este faz apenas duas substituições, independentemente do número de pontos que precedem o = , 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 em sua entrada de amostra).
Uma abordagem mais genérica que sempre substitui somente até 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

gera:

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
    
por 05.11.2015 / 13:50