sed:異なるパターン内でパターンを置き換える

sed:異なるパターン内でパターンを置き換える

$SOME_TEXT_HERE$このような値を次のような値に置き換えたいと思います。@some.text.here@ つまり:

  1. テキストを小文字に変更
  2. $使用。 。 。交換@
  3. 下線をドットに置き換える

最初の文字列には関係のないテキストがいくつかあります。ドルで区切られたテキストはいくらでも変更できます。ドルで区切られたテキストは、下線で区切られた1つ以上の大文字で構成できます。

ステップ1と2を行う方法を知っています。ステップ3をドル記号の中にあるものに制限する方法が気になります。

いいですね。例は次のとおりです。

から: Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$

到着する: Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

私はこれをしました: echo 'Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$ ' |sed -e 's/\$\([A-Z]\+_\?\)\+\$/\L&/g' -e's/\$\(\([a-z]\+_\?\)\+\)\$/@\1@/g'

これは作る: Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing_elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et_dolore_magna_aliqua@

@シンボル内のすべての単語を取得するために一致するグループの結果を繰り返す方法がわかりません。常に最後に一致する結果が得られます。

答え1

パールの使用:

$ cat file
Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
$ perl -pe 's/\$([[:upper:]_]+)\$/"@" . lc $1 =~ tr[_][.]r . "@"/eg' file
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

ここで使用されるPerl式は次のとおりです。

s/\$([[:upper:]_]+)\$/"@" . lc $1 =~ tr[_][.]r . "@"/eg

これは、最初の文字$、1つ以上の大文字、または下線、他の文字で$構成される部分文字列に適用される代替です。

$1代替パターンは、演算子を使用してパターン()の角かっこグループと一致する部分文字列の下線をすべてドットに変更し、結果を小文字にtr変更するPerl式ですlc。次に、@結果の前後に文字を追加します。

これは、Perlが代替テキストを単純なテキストではなくPerl式として扱うことを可能にする式/eフラグです。s///すべての一致に対して置換を繰り返すには、このフラグを使用します/g

答え2

$string入力がシェルの変数に保存されたら、次のことがzshできます。

set -o extendedglob
string=${string//(#b)\$([A-Z]##(_[A-Z]##)#)\$/@${(L)match[1]//_/.}@}

perl同じ

string=$(
  printf '%s\n' "$string" | perl -pe '
    s{\$[A-Z]+(_[A-Z]+)*\$}{lc$& =~ y/_$/.@/r}ge'
)

または:

string=$(
  printf '%s\n' "$string" | perl -pe '
    s{\$[A-Z]+(_[A-Z]+)*\$}{$& =~ y/A-Z_$/a-z.@/r}ge'
)

違いは、ロケールによってperlバイトレベル(ASCIIベースのシステムではASCIIエンコードが必要)とzsh文字レベル(文字でデコードできない場合はバイトに置き換え)で機能することです。エンコーディングを設定します。改行文字で終わっても$string動作が異なります。これは、コマンド置換によってその文字が削除されるためです。

答え3

GNUの使用sed:(必要に応じてsed

$ sed -E 's/\$([A-Z]+([A-Z]*_)*[A-Z]+)\$/@\L\1@/g;s/@([a-z]+)_/@\1./g;s/_([a-z]+)@/\.\1@/g; :X s/(\.[a-z]+)_/\1\./g; tX'

出力:

$ echo 'Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$' | sed -E 's/\$([A-Z]+([A-Z]*_)*[A-Z]+)\$/@\L\1@/g;s/@([a-z]+)_/@\1./g;s/_([a-z]+)@/\.\1@/g; :X s/(\.[a-z]+)_/\1\./g; tX'
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

答え4

もう少し短いGNUsed

sed -E "s/\\\$([A-Z_]+)\\\$/@\L\1@/g; :X s/(@[a-z.]+)_/\1./; tX" file

これが@ソースで自然に発生するのではなく、$最初にのみ発生すると仮定します。[A-Z_]

Lorem $IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
Lorem @ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

これはあなたの例ではうまくいきますが、代わりに$BLAH_BLAH$blah_-> を使用すると失敗します。@blah.blah@blah.@blah.blah@blah_

編集するRe@Quasimodoコメント+- >*セカンドsed

sed -E "s/\\\$([A-Z_]+)\\\$/@\L\1@/g; :X s/(@[a-z.]*)_/\1./; tX" file

Lorem $_IPSUM$ $dolor_sit_amet _ _ _ consectetur $ADIPISICING_ELIT$ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ $ET_DOLORE_MAGNA_ALIQUA$
Lorem @.ipsum@ $dolor_sit_amet _ _ _ consectetur @adipisicing.elit@ sed do $EUISMOD_TEMPOR INCIDIDUNT_UT_LABORE$ @et.dolore.magna.aliqua@

関連情報