awkを使用してフィールド1で最後に表示される特定の文字を置き換える方法

awkを使用してフィールド1で最後に表示される特定の文字を置き換える方法

awkを使用して、最初のフィールドで最後のピリオドをセミコロンに置き換えようとしています。フィールド区切り記号もセミコロンです。

これをregex101.comで正規表現でテストした結果、(\.)(?!.*\1)「abcmp3」を入力として提供したときに最後のピリオドが正しく強調表示されました。

私はawkで次のことを試しました。

awk 'BEGIN{FS=OFS=";"} {gsub(/(\.)(?!.*\1)/, ";", $1)} 1'

それは何も置き換えません。

この問題を助けてくれる人なら誰にも大変感謝します。

ベストアンサー1

AFAIK、awkの実装はPCREツアーをサポートしていません(?!re)

GNU awk(別名 gawk)では、以下を使用します。関数を使用すると、その期間より前のすべてを貪欲にキャプチャし、交換時にそれらを元に戻すことができます。

$ echo 'foo.bar.baz;something;else' | 
    gawk 'BEGIN{OFS=FS=";"} {$1 = gensub(/(.*)\./,"\\1;","1",$1)} 1'
foo.bar;baz;something;else

ポータブルとして使用できますマッチ関数を使用して再度欲張りマッチングを実行し、ピリオドの前後の部分文字列を選択します。

$ echo 'foo.bar.baz;something;else' | 
    mawk 'BEGIN{OFS=FS=";"} match($1,/.*\./){$1 = substr($1,1,RLENGTH-1) ";" substr($1,RLENGTH+1)} 1'
foo.bar;baz;something;else

matchGNU awkを使用すると、オプションの配列引数を使用して、キャプチャと逆置換を(これも移植不能に)使用できます。

$ echo 'foo.bar.baz;something;else' | 
    gawk 'BEGIN{OFS=FS=";"} match($1,/(.*)\.(.*)/,a){$1 = a[1] ";" a[2]} 1'
foo.bar;baz;something;else

プレビューはPerlと互換性があるため、もちろんPerlを使用できます(たとえキャプチャや逆参照がなければ、\.どんな場合でも過剰になるかもしれません)。

$ echo 'foo.bar.baz;something;else' | 
    perl -F';' -pe '$_ = join ";", $F[0] =~ s/\.(?!.*\.)/;/r, @F[1..$#F]'
foo.bar;baz;something;else

ミラーawkに似てsubおり、gsubGNU awkと同様に、キャプチャgensubと逆参照をサポートしています。

$ echo 'foo.bar.baz;something;else' | 
    mlr --nidx --fs ';' put '$1 = sub($1,"(.*)\.","\1;")'
foo.bar;baz;something;else

私が知っている限り、現在はツアーをサポートしていません。

おすすめ記事