3

4 列の CSV ファイルがあります。例:

0001 @ fish @ animal @ eats worms

以前はファイルに対して検索と置換を行っていsedましたが、この検索と置換を列 3 内にあるテキストのみに制限する必要があります。

この 1 つの列でのみ検索と置換を行うにはどうすればよいですか?

4

3 に答える 3

4

本当に を使用しsedますか? どうcsvfixですか?あなたのCSVは、引用符や埋め込まれたコンマ、または正規表現を作成するその他の厄介なものがなく、素晴らしくシンプルですか...一般的なCSVファイルを処理する方法として満足のいくものではありませんか? @は、フォーマットの「コンマ」であると想定しています。

awkの代わりに使用することを検討してくださいsed:

awk -F@ '$3 ~ /pattern/ { OFS= "@"; $3 = "replace"; }'

おそらく、OFS を 1 回設定する BEGIN ブロックが必要です。1 行の入力では、何のオッズもありませんでした (そして、100 万行の入力の違いを測定するのもおそらく難しいでしょう):

$ echo "pattern @ pattern @ pattern @ pattern" | 
> awk -F@ '$3 ~ /pattern/ { OFS= "@"; $3 = "replace"; }'
pattern @ pattern @replace@ pattern
$

sedそれでも魅力的だと思われる場合は、次のようにします。

sed '/^\([^@]*@[^@]*\)@pattern@\(.*\)/ s//\1@replace@\2/'

例 (入力と出力がわずかに異なることに注意してください。必要に応じて、awk 非常に簡単に同じように処理するように修正できます):

$ echo "pattern@pattern@pattern@pattern" |
> sed '/^\([^@]*@[^@]*\)@pattern@\(.*\)/ s//\1@replace@\2/'
pattern@pattern@replace@pattern
$

最初の正規表現は、行頭、非アットマークのフィールド、アットマーク、非アットマークの別のフィールドを探し、ロットを記憶します。アットマーク、パターン (最初の 2 つのフィールドは既に一致しているため、パターンは 3 番目のフィールドにある必要があります)、別のアットマーク、そして行の残りを探します。行が一致すると、その行が最初の 2 つのフィールド (必要に応じて変更なし) に置き換えられ、次に、置換された 3 番目のフィールドと行の残り (必要に応じて変更されない) が追加されます。

3 番目のフィールドを単純に置き換えるのではなく、編集する必要がある場合は、awkPerl または Python の使用を検討します。それでも に制約されている場合はsed、ホールド スペースを使用してラインの一部を保持し、パターン スペースで他の部分を操作して、印刷前にホールド スペースとパターン スペースから目的の出力ラインを再統合することになります。この線。それは聞こえるほど厄介です。実際には、思ったよりも厄介かもしれません。私は Perl を使いますが (私はずっと前に Perl を学び、この種のことを非常に簡単に実行できるため)、sedツール以外の好きなものを使用できます。


3 番目のフィールドを編集する Perl。デフォルトの出力は$_、配列内の自動分割フィールドから再構築する必要があることに注意してください@F

$ echo "pattern@pattern@pattern@pattern" | sh -x xxx.pl
> perl -pa -F@ -e '$F[2] =~ s/\s*pat(\w\w)rn\s*/ prefix-$1-suffix /; $_ = join "@", @F; ' "$@"
pattern@pattern@ prefix-te-suffix @pattern
$

説明。 これは、「ループし、各反復の最後に-p行を読み込ん$_で印刷する」ことを意味します。$_これは、「配列に-a自動分割」することを意味します。は、フィールド セパレータが であることを意味します。この後に Perl プログラムが続きます。Perl では配列は 0 からインデックス付けされるため、3 番目のフィールドは(シジル — or — は、配列の値を操作するか、配列全体の値を操作するかによって変化します。は一致演算子です。は、RHS の正規表現を LHS の値に適用します。置換パターンは、0 個以上のスペースとそれに続く2 つの「単語」文字を認識し、$_@F-F@@-e$F[2]@$=~\s*pat$1rnそして再びゼロ以上のスペース。フィールドの開始と終了にバインドする^andがそこにあるはずです。$置換は、スペース、'prefix-'、記憶された文字のペア、および'-suffix' とスペースです。は、変更された可能性のある個別のフィールドから$_ = join "@", @F;入力行を再構築し、それを出力します。私が望むほどきれいではありません(おそらくもっと良い方法があります)が、うまくいきます。また、Perl では、任意のフィールドに対して任意の変換を簡単に行うことができます。Perl には、非常に複雑な CSV ファイルを処理できるモジュール(および高速な C バージョン) もあります。$_-pText::CSVText::CSV_XS

于 2012-04-07T01:06:25.080 に答える
1

これはあなたのために働くかもしれません:

echo 0001 @ fish @ animal @ eats worms|
sed 's/@/&\n/2;s/@/\n&/3;h;s/\n@.*//;s/.*\n//;y/a/b/;G;s/\([^\n]*\)\n\([^\n]*\).*\n/\2\1/'
0001 @ fish @ bnimbl @ eats worms

説明:

  1. 作業するフィールド(この場合は3番目)を定義し、その\n前と直後に改行()を挿入します。s/@/&\n/2;s/@/\n&/3
  2. 保留スペースに行を保存します。h
  3. いずれかの側のフィールドを削除しますs/\n@.*//;s/.*\n//
  4. 次に、フィールドを処理します。つまり、すべてa'sをに変更しb'sます。y/a/b/
  5. 次に、元の行を追加します。G
  6. 古いフィールドを新しいフィールドに置き換えます(改行も削除します)。s/\([^\n]*\)\n\([^\n]*\).*\n/\2\1/

注意:ステップ4では、パターンスペースには定義されたフィールドのみが含まれているため、ここで任意の数のコマンドを実行でき、結果は行の残りの部分に影響しません。

于 2012-04-07T07:19:47.667 に答える
1

基本的に、探しているパターンを真ん中にして、線を 3 つに分けます。次に、外側のピースを残し、中央を交換します。

/\([^@]*@[^@]*@\[^@]*\)pattern\([^@]*@.*\)/s//\1replacement\2/

\([^@]*@[^@]*@\[^@]*\)- 3 番目の @ と数式の前のテキストを含む、パターンの前のすべてを収集します - これは \1 になります

pattern- あなたが探しているもの

\([^@]*@.*\)- パターンの後にすべてを集めます - これは \2 になります

\1次に、その行を に変更しreplacement、その後のすべてを変更しpatternます。\2

于 2012-04-07T01:16:43.613 に答える