4

高度にカスタマイズされた形式を使用する CSV ファイルがあります。ここで、各数値は 4 つの列のそれぞれのデータを表します。

1 2 [3] 4

sed4 番目の列に表示されるデータのみを検索および変更するように制限する必要があります。基本的に、閉じ角括弧とスペースが最初に出現する前の行のすべてのデータを無視し、]その後に出現するデータのみを変更する必要があります。たとえば、次の内容file1.txtが含まれる場合があります。

penguin bird [lives in Antarctica] The penguin lives in cold places.
wolf dog [lives in Antarctica with penguins] The wolf likes to eat penguins.

交換品はsed 's/penguin/animal/g' file1.txt. スクリプトを実行すると、出力は次のようになります。

penguin bird [lives in Antarctica] The animal lives in cold places.
wolf dog [lives in Antarctica with penguins] The wolf likes to eat animal.

この場合、penguin最初の行より前のすべての出現は無視され、]後に出現する行でのみ変更されました。

  • 行の後半に追加の閉じ括弧が表示される場合がありますが、最初のものだけが分割と見なされます。

sedテキストを検索して置換する際に、このカスタム CSV 形式の最初の 3 列を無視するにはどうすればよいですか?

GNU sed バージョン 4.2.1 を使用しています。

4

4 に答える 4

3

sed に '] ' の組み合わせとそれに続く (何でも) を検索するように指示し、置換の一部として文字.*を元に戻します。]

唯一の問題は、通常、 char は文字クラス定義の一部であるsedと「考える」ため、エスケープする必要があることです。]試す

echo "a b [c] d" | sed 's/\] .*$/\] XYZ/'
a b [c] XYZ

[char-class def を示す最初の charがなかったため、

echo "a b [c] d" | sed 's/] .*$/] XYZ/'
a b [c] XYZ

編集

4 番目の単語だけを修正するには、

echo "a b [c] d e" | sed 's/\] [^ ][^ ]*/\] XYZ/'
a b [c] XYZ e 

上記の追加で[^ ][^ ]/は、「スペースではない任意の文字」の後に任意の数の「スペースではない任意の文字」が続くため、マッチャーが次のスペースを見つけると、一致を停止します。

最終編集

echo "penguin bird [lives in Antarctica] The penguin lives in cold places.
wold dog [lives in Antarctica with penguins] The wolf likes to eat penguins." \
| sed 's/\] The penguin \(.*$\)/] The animal \1/'

(...また、gnu sed を使用しているため、 ) をキャプチャする括弧をエスケープする必要はありません。

echo "penguin bird [lives in Antarctica] The penguin lives in cold places.
wold dog [lives in Antarctica with penguins] The wolf likes to eat penguins." \
| sed 's/\] The penguin (*$)/] The animal \1/'

出力

penguin bird [lives in Antarctica] The animal lives in cold places.
wolf dog [lives in Antarctica with penguins] The wolf likes to eat penguins.

使用している sed のバージョンによって異なります。, vs , VS の間にはかなり大きな違いがあり、 Lunixsedで通常見られる GNU sed があります。AIXsolaris

sed の使用について他に質問がある場合は、通常sed --version、またはの出力を含めると役立ちますsed -V。これらのコマンドから応答がない場合は、 を試してくださいwhat sed。それ以外の場合は、の OS 名を含めますuname

IHTH

于 2012-09-17T00:13:04.357 に答える
2

閉じ括弧が1回だけ出現すると仮定すると、awkこれを行うために使用します。

awk 'BEGIN {FS=OFS="]"} { gsub(/penguin/, "animal", $2) }1' file.txt

結果:

penguin bird [lives in Antarctica] The animal lives in cold places.
wolf dog [lives in Antarctica with penguins] The wolf likes to eat animals.
于 2012-09-17T00:33:09.223 に答える
2

通常、私はshelterが説明した方法でそれを行います(簡単なコマンドラインを入力しただけの場合)が、入力の一部を一致させて保持する(など)と、すべてを一致させて置き換える必要sedがあるという欠点があります\1のような単純な置換は使用できなくなりましs/penguin/animal/た。置換の前後にボイラープレートを追加したい場合は、ホールド バッファー内の行の先頭を隠してから、元に戻すことができます。

sed -e 'h' \
    -e 's/.*\] //' \
    -e 's/penguin/animal/' \
    -e 'x' \
    -e 's/\] .*/] /' \
    -e 'G' \
    -e 's/\n//'

は元のh回線をホールド スペースに保存します。次に、接頭辞を削除し、行末で置換 (ここで例を選択) または一連の置換を行います。次にx、最後と保存されたコピーを交換します。保存されたコピーから元の端を削除し、Gそれらを元に戻すために使用します。はG不要な改行を追加するので、それを削除します。

于 2012-09-17T00:40:37.937 に答える
1

これはうまくいくかもしれません(GNU sed)。

sed  -i 's/\]/&\n/;h;s/.*\n//;s/penguin/animal/g;H;g;s/\n.*.\n//' file

説明:

  • s/\]/&\n/\nマーカーで線を分割
  • h行をコピーする
  • s/.*\n//変更したくない行の部分を削除します
  • s/penguin/animal/g変えたい部分を変える
  • H;g元の行に追加します
  • s/\n.*\n//変更したい元の行の部分を削除します

これはすべての行に適用されます。変更が条件付きの場合は、次を使用します。

sed  -i '/\]/!b;s//&\n/;h;s/.*\n//;s/penguin/animal/g;H;g;s/\n.*.\n//' file

別の方法 (おそらくもっと簡単な方法):

sed ':a;s/\(\].*\)penguin/\1animal/;ta' file
于 2012-09-17T05:42:07.373 に答える