awkのgensubまたは代替を使用して重複する一致を置き換える方法

awkのgensubまたは代替を使用して重複する一致を置き換える方法

私は以下を使用しています:

$ echo ".a.b.c." | awk '
{
  t=gensub(/.([a-z])./,"[\\1]","g",$1); print t
}'
[a]b[c]

私はそれを終了したい[a][b][c]gensub重複一致処理を開始するにはどうすればよいですか?

これができない場合、どうすればこれを達成できますか?

答え1

次のようにできます。

perl -pe 's{\.([a-z](?:\.[a-z])*)\.}{"[$1]" =~ s/\./][/gr}ge'

つまり、すべてをに変更し、.x.y.z.sを[x.y.z].置き換えます][

またawkgensub()成功の有無を教えてくれないので、具体的で使いにくいgawkの使用を避けてください。

awk '
  {
    while(match($0, /(\.[abcdefghijklmnopqrstuvwxyz])+\./)) {
      s = substr($0, RSTART + 1, RLENGTH - 2)
      gsub(/\./, "][", s)
      $0 = substr($0, 1, RSTART - 1) "["s"]" substr($0, RSTART+RLENGTH)
    }
    print
  }'

現在のバージョンmawk(まだローカライズされていない)または最新バージョンを使用している場合、またはgawkCロケールの場合abcdefghijklmnopqrstuvwxyzに置き換えることができますa-z。これらの条件を超えた場合、同一であるという保証はありません。特に、一部のロケールでは、[a-z]各 POSIX は次の順序に一致するように設計されています。要素の構成、いいえ数値ddzsハンガリー語のロケールのように複数の文字を一致させることもできます。

とにかく正規表現で文字通りのポイントを一致させるには、\.またはが必要です[.].それ以外の場合は、それ自体が単一文字に一致する正規表現演算子です。

答え2

通常、正規表現エンジンは重複する一致を考慮しません。これは提案された方法ではありませんが、後者の一致は以前の置換によって挿入された文字を考慮しません。

Perlでは、Lookbehindを使用して閉じる角かっこの右側を一致させ、操作が実行された回数だけ(文字列全体で)置換を繰り返すことができます。ここでは、リテラルポイント間の文字を一致させたいとします(正規表現は単一の.文字と一致します)。

% cat test.txt
.a.b.c.
..a..
.a.b  c.d.
.a]b.
% perl -pe '1 while s/(\.|(?<=\]))([a-z])\./[$2]/'  < test.txt
[a][b][c]
.[a].
[a]b  c[d]
.a][b]

最後の行には、]次の一致が現在トリガーされている偽の肯定が表示されますb.。まず、入力にないようないくつかのバイトを挿入し、それを実際の角かっこに置き換えることでこれを防ぐことができます。たとえば、バイト値1、^ A:

% perl -pe '1 while s/(\.|(?<=\001))([a-z])\./[$2\001/; tr/\001/]/' < test.txt
[a][b][c]
.[a].
[a]b  c[d]
.a]b.

私が見つけられなかった他の問題があるかもしれません。置換を繰り返すときに一致が緩すぎると、無限ループに陥る危険がありますが、置換にはリテラルポイントが必要で、常に少なくとも1つのポイントを削除するため、危険ではありません。

.(正規表現のどんな文字と一致するという意味abcdなら、例えばにならなければならないようですが[b]d、おかしいようです。)

答え3

これはルビーです:

echo ".a.b.c." | ruby -pe '$_.gsub!(/(?:[.][a-z](?=\.))|\./){|m| m[/^\.$/] ? "" : "[#{m[1]}]" }'

またはパール:

echo ".a.b.c." | perl -pe 's/(?:[.]([a-z])(?=\.))|\./($1 eq "") ? "" : "[$1]" /ge'

または、以下を印刷してください。

[a][b][c]

関連情報