如果某个字符出现在另一个字符之前,则替换该字符的所有实例

如果某个字符出现在另一个字符之前,则替换该字符的所有实例

我需要能够从文件中导出一些变量,以便我可以在 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}'

现在,如果右侧包含=shell 特有的字符(\“$&();'#~<>...`、空格、制表符、其他空格...),您可能需要引用它:

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

我们使用参数扩展模式将变量名称中的所有s${i//./_}替换为 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

相关内容