web-dev-qa-db-ja.com

特定の列レベルの置換

列のエントリを含むファイルがある場合、特定の列の特定のエントリのみを置き換えて、同じファイルに変更を保存することはできますか?

ファイルの例abc.txt

SR|FRUITS|COLOR|
1|Apple|Red|
2|Mango|Yellow|
3|Orange|Orange|
4|W.Melon|Green|

OrangeをfruitsからOrange_Editに変更する必要があります。ただし、オレンジ色は影響を受けません。

3
abhishek nair

awkのように2つのステップでそれを行うことができます

awk '{$2="VAL";print}' input_file > temp_file
mv temp_file input_file

これにより、入力ファイルが空白で分割され、2番目の列の値が置き換えられ(別の列には2以外の数値を使用)、「VAL」になります。 OFSで変更しない限り、出力フィールドの区切り文字はスペースになります。他に何かが必要な場合は、引用符の中に「BEGIN {OFS = "\ t"} ...」のように追加して、出力フィールドの区切り文字を任意に設定できます。

値を定数以外のものにしたい場合は、もう少し作業が必要になりますが、これを調整して実行できます。

あなたのケースで編集のためにこれを機能させるには、次のことができます。

awk -F\| 'BEGIN {OFS="|";} $2~/^Orange$/ {$2="Orange_edit";} {print}' abc.txt > temp_file
mv temp_file abc.txt

これは最初に、|を渡すことにより、-F\|に基づいてフィールドを分割するようにawkに指示します。次に、コードの最初のブロック(BEGINに一致する部分、開始に一致するawkのキーワード)を作成することにより、出力区切り文字(デフォルトはスペース)にも|を使用するように出力を設定します。実行の)そしてOFS、または出力フィールドセパレータを設定します。 Otheusが指摘したように、{OFS=FS}を実行して、出力区切り文字を入力区切り文字と同じに設定できます。

その後、線を見始めます。 $2によって参照される2番目のフィールドを比較し、~を使用して正規表現と一致するかどうかを確認します。 ~が一致させたい正規表現の後に、^はフィールドの先頭に一致することを意味し、次に文字列 "Orange"があり、次に$がフィールドの終わりに一致します。これはハードコードされた文字列であるため、Otheusも正しく観察しました。代わりに、ここで文字列の同等性をテストし、$2=="Orange"を実行して、今回は実際には何も実行しないため、正規表現処理をスキップできます。その一致が実行後に{}のコードのブロックに成功すると、2番目のフィールドに新しい値が保存されます。

最後に、すべての行に対してコード{print}の最後のブロックを実行しますが、上記で「オレンジ」の一致が成功すると、2番目のフィールドの値が変更されたため、古い値ではなく新しい値で出力されます。

awkは通常画面に出力されるので(明らかに新しいgawkにはこの部分を合理化するオプションがあります)、それをファイルに保存してから、そのファイルを元の名前に戻します。

4
Eric Renouf

Perlを使用できます:

$ Perl -i.bak -F'\|' -aple 's/Orange/Orange_Edit/ if $F[1] eq "Orange"' file

またはより安全なバージョン:

$ Perl -i.bak -F'\|' -aple '$F[1]=~s/^Orange$/Orange_Edit/; $_=join "|",@F' file
2
cuonglm

これを行うには多くの方法があります。最も単純なのはおそらくawkPerlです。

  1. GNU gawkgawkの比較的新しいバージョンがインストールされている場合は、次のようにインライン編集を行うことができます。

    _gawk -i inplace -F"|" -vOFS="|"  '$2=="Orange"{$2="Orange_Edit"}1;' file 
    _

    _-i inplace_はgawkにファイルをインプレースで編集するように指示し、_-F"|"_はフィールド区切り文字を_|_に設定し、_-vOFS="|"_は出力フィールド区切り文字を_|_も同様です。スクリプトは、2番目のフィールドがOrangeの場合にのみ、2番目のフィールド(_$2_)を_Orange_Edit_に設定します。 _1;_は、「現在の行を出力する」のawk省略形です。

  2. Perl

    _Perl -i -F"\|" -lane '$F[1]="Orange_Edit" if $F[1] eq "Orange"; 
                       print join "|",@F' file 
    _

    _-a_は、Perlをawkのように動作させ、_-F_で指定された値で行を分割し、結果のフィールドを_@F_配列に保存します。次に、元の値がOrangeの場合、スクリプトは2番目のフィールド(_$F[1]_、配列は0から始まります)を_Orange_Edit_に設定します。次に、フィールドは_|_で結合され、出力されます。

  3. Orangeの最初のオカレンスを変更したいだけの場合は、単純化して使用できます。

    _sed -i 's/Orange/Orange_Edit/' file 
    _

    フィールド全体を照合するだけで、これをもう少し堅牢にすることができます。

    _sed -i 's/|Orange|/|Orange_Edit|/' file 
    _
2
terdon