Мне нужно экспортировать некоторые переменные из файла, чтобы использовать их в моем скрипте BASH. Содержимое файла примерно такое:
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
Сначала я попытался использовать его source
как есть и получил сообщение об ошибке: command not found
. Я попытался использовать export
, что дало мне сообщение об ошибке: not a valid identifier
.
Я думаю, что я могу экспортировать только если изменю свою переменную с my.variable.var1
на my_variable_var1
.
Я могу сделать это, обрезав строку at =
и заменив все .
s на _
s, а затем добавив переменные обратно.
Итак, мой вопрос: возможно ли изменить:
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
к
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
используя любой из этих крутых "однострочников"? С удовольствием бы использовал это, плюс хорошее обучение.
решение1
С sed
:
sed -e :1 -e 's/^\([^=]*\)\./\1_/;t1'
То есть заменить последовательность символов, отличную от .
начала строки, на .
ту же самую последовательность и _
, и повторять процесс до тех пор, пока совпадения не исчезнут.
С awk
:
awk -F = -v OFS== '{gsub(/\./, "_", $1); print}'
Теперь, если правая часть содержит =
специальные символы оболочки ( \
"$&();'#~<>...`, пробел, табуляция, другие пробелы...), вы можете захотеть заключить ее в кавычки:
sed "s/'/'\\\\''/g;:1"'
s/^\([^=]*\)\./\1_/;t1'"
s/=/='/;s/\$/'/"
Или:
awk -F = -v q="'" -v OFS== '
{gsub(q, q "\\" q q)
gsub(/\./, "_", $1)
$2 = q $2
print $0 q}'
решение2
С использованием bash
:
while IFS='=' read -r i j; do echo "${i//./_}=$j" ; done
Мы использовали шаблон расширения параметров ${i//./_}
, чтобы заменить все .
s на _
s в имени переменной.
Пример:
$ 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
решение3
Вот еще sed
:
sed 'h;s/\./_/g;G;s/=.*=/=/'
Этот пример делает только две замены, независимо от количества точек, предшествующих so, =
при вводе следующего вида:
my.var.an.other.var.with.many.dots=line.with.many:chars:and_numbers.and.stuff
результат есть
my_var_an_other_var_with_many_dots=line.with.many:chars:and_numbers.and.stuff
Это работает нормально, когда в =
строке один символ (как в вашем примере ввода).
Более общий подход, который всегда заменяет только до первого =
(и только если строка содержит хотя бы один =
), даже если в строке несколько =
символов:
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 =
или
sed -e '/=/{h;s/\./_/g;G;s/=.*\n[^=]*=/=/' -e '}'
поэтому с такими входными данными, как:
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
выводит:
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