ファイル内に複数の行similarがあるとしましょう。
Turbo is a cat. cats are good. cats are not dog.
Coco is a black cat. cats are furry. cats are not dog.
さて、grep
すべての^.*cat
ただし、単語cat
が最初(またはn番目)に出現するまでキャプチャすることについて特に言及したいと思います。
必要な出力:
Turbo is a cat
Coco is a black cat
*blah is a so and so cat*
どうすればgrep
できますか?
PS:grep
(またはそのその他のバリエーション)のみを使用して回答したいと思います。
PS:grepしたくない^.*cat.
次に、任意の操作を実行して"。"を削除します。一般的な答えが欲しいです。
POSIX grepを使用すると、行全体を印刷するか、行の内容をまったく印刷しないかを選択できます。線を変換する場合は、sedやawkなどの別のツールを使用する必要があります。 cat
が最初に出現するまで印刷するには:
sed -n 's/cat.*/cat/'
awk 'sub(/cat.*/,"")'
[〜#〜] n [〜#〜]番目のオカレンスまでの印刷はより複雑です。
sed -n 's/cat/&\
/3; T; P'
awk 'gsub(/cat/,"&\n") >= 3 {split($0, a, "\n"); printf "%s%s%s\n", a[1], a[2], a[3]}'
GNU grepを使用すると、-o
オプションを使用して、行の一致した部分のみを印刷できます。 -P
オプションを使用してPerl構文をアクティブにし、 貪欲でない量指定子 が使用できるようにします。
grep -P -o '^(.*?cat){1}'
中括弧内の数字を、最後に出現したcat
の数字nに置き換えます。
拡張正規表現(-E
)で同じことを表現することは可能ですが、これには複雑な正規表現が必要です。そのサイズは、カウントするパーツのサイズ(ここではcat
)で指数関数的です。
grep
は、指定された正規表現に基づいて行のみを選択し、それらを出力します。
私はあなたが出力ラインをパイプし、仕事をするために追加のコマンドを使用することを余儀なくされていると思います。
通常、sed
またはawk
を使用して、grep
なしでジョブを実行します。これは、行の選択と文字列の置換の両方が可能なためです。
awk
を使用した以下の解決策があります。
awk -v Word=cat -v n=2 'BEGIN {wordlength=length(Word);} {line=$0;outputline="";position=index(line,Word);for (i=1;position>0 && i<=n; i++) { outputline=outputline substr(line,1,position+wordlength-1);line=substr(line,position+wordlength);position=index(line,Word); } if (i!=1) {print outputline;}}'
検索する文字列にWord
を設定し、必要な出現回数にn
を設定する必要があります。
テスト:
$ awk -v Word=cat -v n=2 'BEGIN {wordlength=length(Word);} {line=$0;outputline="";position=index(line,Word);for (i=1;position>0 && i<=n; i++) { outputline=outputline substr(line,1,position+wordlength-1);line=substr(line,position+wordlength);position=index(line,Word); } if (i!=1) {print outputline;}}' file
Turbo is a cat. cat
Coco is a black cat. cat
これがsed
ソリューションです(たとえば、2番目のオカレンスまで印刷します。2
をあなたの番号に置き換えます):
sed -n 's/cat/&\
/2
t print
d
:print
P' infile
これにより、-n
による自動印刷が無効になり、2番目に出現するcat
をcat
+改行文字に置き換えようとします。置換が成功すると、:print
に分岐し、改行までP
rintsします。それ以外の場合、行はd
eletedになります。
gnu sed
を使用すると、ワンライナーとして書くことができます(たとえば、5回目までの印刷):
sed -n 's/cat/&\n/5;tt;d;:t;P' infile