次の行にbarが含まれていない場合は、fooを含む行と一致させたいと思います。したがって、以下を含むファイルが提供されます。
1 foo 1
foo 2
baz bar bap
印刷のみです1 foo 1
。私は/foo(?!.*\n.*bar)/
それが動作するように否定的な予測を使用しました。https://regex101.com/r/ZMZsiN/1しかし、grepとperlを使用してコマンドラインで使用することはすべて失敗しました。 Perl、sed、awk、またはPythonでgrepまたは1行ステートメントを使用するすべてのソリューションは素晴らしいでしょう。 Chatgptが失敗しました。
試してみる:
$grep -Pwe 'foo(?!.*\n.*bar)' testfile
1 foo 1
foo 2
$perl -wnl -e /'foo(?!\n.*bar)/ and print' testfile
1 foo 1
foo 2
$perl -ne 'print if /foo/ && ($_ = <>) !~ /bar/' testfile
foo 2
最後は、chatgptが提供するものに基づいており、近いですが、私のperlfuはまだ問題を特定するのに十分ではありません。
ベストアンサー1
grep
または、一度にperl -n
1行だけを処理するため、正規表現は1行の内容のみと一致します(行区切り文字はまたは grep
にperl
は含まれません-l
)。
複数pcregrep
行モードと。-P
grep
-M
pcregrep -M '\bfoo\b(?!.*\n.*\bbar\b)'
必要に応じて一致する項目にさらに行をインポートすることに加えて、複数行モードは項目の開始と終了だけでなく、すべての行の開始と終了で一致するフラグ(暗黙的に)を有効にpcregrep
します。m
(?m)
^
$
いいえこのフラグを有効にすると、改行文字が一致しないことを意味しs
ます。.
(\b
単語b
の境界、-w
役に立つところに単語の境界を置かない)。
を使用すると、perl -n
正規表現がファイル全体で一致することができないようにレコード区切り文字を設定できます。
perl -0777 -ne '
print for m{^.*\bfoo\b.*\n(?!.*\bbar\b)}mg'
標準のUnixツールボックスを使用することは可能ですsed
が、標準にはsed
単語境界演算子がないため、不器用な回避策が必要です。
sed -n '/^\(.*[^[:alnum:]_]\)\{0,1\}foo\([^[:alnum:]_].*\)\{0,1\}$/ {
$!N
/\n\(.*[^[:alnum:]_]\)\{0,1\}bar\(.*[^[:alnum:]_]\)\{0,1\}.*$/!P
D
}'