ある文字が別の文字の前に出現する場合、その文字のすべてのインスタンスを置換します。

ある文字が別の文字の前に出現する場合、その文字のすべてのインスタンスを置換します。

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.var1my_variable_var1
行を切断し=、すべての.を に置き換えて_から、変数を再度追加することで、これを実行できます。

そこで質問なのですが、変更することは可能でしょうか:

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

パラメータ拡張パターンを使用して、変数名内のすべてのs を s に${i//./_}置き換えました。._

例:

$ 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 の前のドットの数に関係なく、2 つの置換のみを実行します。

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

これは、1 行に 1 つの文字がある場合=(サンプル入力のように) は正常に機能します。1行に複数の文字がある場合でも、常に最初の文字まで(行に少なくとも 1 つの が含まれている場合のみ)
のみを置換する、より一般的なアプローチは次のとおりです。===

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

関連情報