awkとsedを使用して文字の部分文字列を置き換える

awkとsedを使用して文字の部分文字列を置き換える

非常に長い文字列を含むファイルがあり、その部分文字列をNに置き換えたいと思います。例:

テスト

ABCDABCDABCD

awkコマンドとsedを使用して、部分文字列をすべての文字N(インデックス5から8までのすべての文字)に置き換えたいので、文字Nの合計長は4です。

出力

ABCDNNNNABCD

私は次のことを試しました:

awk '{ v=substr($0,5,4); sed -i "s/$v/N/g";print substr($0,1,4)""v""substr($0,9,12)}' test

ただし、このコマンドは次の出力を提供するようです。

ABCDABCDABC

そして交換は行われませんでした

交換を開始する場所のインデックス番号(例:5)と交換長番号(ここでは4)をコードに含めたいと思います。したがって、開始したい場合は、その数を変更できます。実際には、何千もの文字で構成された文字列があり、何百もの文字を置き換えたいので、私の場合はパターン置換が機能しないので、別の場所で別の長さの置換を実行してください。

答え1

GNU awkを使用すると、次のことができます。

gawk -v start=5 -v end=8 '{
    mid = substr($0, start, end-start+1)
    print substr($0, 1, start-1) gensub(/./, "N", "g", mid) substr($0, end+1)
}' file

またはパールを使用してください

perl -spe 'substr($_, $start-1, $end-$start+1) =~ s/./N/g' -- -start=5 -end=8 file

どちらのソリューションもコマンドラインオプションを使用して、開始値と終了値をプログラムに渡します。これにより、シェルスクリプトで値を簡単に変更できます。代替ロールNを動的に作成する必要がある場合は、これを行う方法は非常に明確でなければなりません。

答え2

GNU awk(gawk)がある場合は、FIELDWIDTHS文字の位置に応じて行をフィールドに分割するように設定できます。これは、「ワイルドカード」末尾のフィールド幅をサポートするgawkバージョン> = 4.2で特に便利です。その後、2番目のフィールドの文字を次のように置き換えることができますgsub

echo ABCDABCDABCD | ./gawk -v i=5 -v n=4 '
  BEGIN {FIELDWIDTHS = sprintf("%d %d *", i-1, n)} 
  {gsub(/./,"N",$2)} 1
' OFS=""
ABCDNNNNABCD

以前のバージョンの gawk では、*末尾フィールドに適切に大きい最大サイズを選択することでこれをシミュレートできます。

echo ABCDABCDABCD | gawk -v i=5 -v n=4 '
  BEGIN {FIELDWIDTHS = sprintf("%d %d 65536", i-1, n)} 
  {gsub(/./,"N",$2)} 1
' OFS=""
ABCDNNNNABCD

バラより

固定幅データ処理

オプションのトレースデータの取得

答え3

次のコマンドを試すことができます。

 echo "ABCDABCDABCD"| sed "s/ABCD/NNNN/2"

出力

ABCDNNNNABCD

答え4

POSIXまたはGNU sedsに示すように、次の方法を使用してこれを実行できます。

sedエディタを使用してください。

$ L=5 R=8
$ sed -e '
   s/./\n/'"$L"';s//\n/'"$R"';ta
   :a;s/\n\n/NN/;t
   s/\n./N\n/;ta
' ./test

ABCDNNNNABCD

パールの使用:

perl -lspe '
   my $c = $idxr - (pos()=$idxl-1);
   s/\G.{$c}/"N"x$c/e;
' -- -idxl=5 -idxr=8 ./test

ABCDNNNNABCD

関連情報