入力ファイル1は次のとおりです。
dog 123 4335
cat 13123 23424
deer 2131 213132
bear 2313 21313
other file
のパターンを([file2のdog 123 4335
のように)一致させます。
行のパターンに一致するのはdog 123 4335
で、一致行のないすべての行を印刷すると、出力は次のようになります。
cat 13123 23424
deer 2131 213132
bear 2313 21313
行のアドレスなしでのみ使用する場合は、パターンのみを使用します。たとえば、1s
行を照合して印刷する方法は?
GNU sed
を使用して、行全体をパターンと一致させたい場合、これは機能します:
sed -n '/^dog 123 4335$/ { :a; n; p; ba; }' infile
標準同等物:
sed -ne '/^dog 123 4335$/{:a' -e 'n;p;ba' -e '}' infile
次の入力(infile
)を使用:
cat 13123 23424
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424
deer 2131 213132
bear 2313 21313
出力は次のとおりです。
cat 13123 23424
deer 2131 213132
bear 2313 21313
/^dog 123 4335$/
は、目的のパターンを検索します。:a; n; p; ba;
は、入力(n
)から新しい行をフェッチして出力し(p
)、次に分岐して:a; ...; ba;
のラベルを付けるループです。これがあなたのニーズに近い答え、つまりfile2のパターン、file1からgreppingです。
tail -n +$(( 1 + $(grep -m1 -n -f file2 file1 | cut -d: -f1) )) file1
埋め込まれたgrepとcutは、file2からのパターンを含む最初の行を見つけます。この行番号に1を加えたものがテールに渡され、1を追加すると、パターンのある行がスキップされます。
最初の一致ではなく最後の一致から開始する場合は、次のようになります。
tail -n +$(( 1 + $(grep -n -f file2 file1 | tail -n1 | cut -d: -f1) )) file1
Tailのすべてのバージョンがプラス表記をサポートしているわけではないことに注意してください。
適度に短いファイルがある場合、grep
だけでも機能する可能性があります。
grep -A5000 -m1 -e 'dog 123 4335' animals.txt
grep
は最初の一致を見つけて次の5000行と一緒に出力するので、5000は「かなり短い」と私が推測しているだけです(ファイルにそれほど多くの必要はありません)。マッチ自体が必要ない場合は、カットする必要があります。
grep -A5000 -m1 -e 'dog 123 4335' animals.txt | tail -n+2
tac animals.txt | sed -e '/dog 123 4335/q' | tac
この行は、行の逆順でanimals.txt
を読み取り、dog 123 4335
の行までを含めて出力し、再び逆転して適切な順序に戻します。
繰り返しになりますが、結果で一致が必要ない場合は、末尾を追加します。 (終了する前に、sed式を複雑にして、そのバッファーを破棄することもできます。)
実際には私はおそらく Aet3miirahの答え をほとんど使用します alexey's answer は行をナビゲートしたいときに素晴らしいです(また、less
)。 OTOH、私は本当に別のアプローチが好きです(それは一種の逆転 Gillesの答え :
sed -n '/dog 123 4335/,$p'
-n
フラグを指定して呼び出された場合、sed
はデフォルトでは、それが処理する行をデフォルトで出力しません。次に、/dog 123 4335/
に一致する行からファイルの終わり($
で表される)までコマンドを適用することを示す2アドレスフォームを使用します。問題のコマンドはp
で、現在の行を出力します。つまり、これは「/dog 123 4335/
」に一致する行から最後まですべての行を出力することを意味します。
sed -e '1,/dog 123 4335/d' file1
ファイルからパターンを読み取る必要がある場合は、sedコマンドに置き換えます。ファイルにsedパターンが含まれている場合:
sed -e "1,/$(cat file2)/d" file1
検索するリテラル文字列がファイルに含まれている場合は、すべての特殊文字を引用符で囲みます。ファイルには1行が含まれていると思います。
sed -e "1,/$(sed 's/[][\\\/^$.*]/\\&/g' file2)/d" file1
一致を部分文字列だけでなく行全体にしたい場合は、パターンを^…$
で囲みます。
sed -e "1,/^$(sed 's/[][\\\/^$.*]/\\&/g' file2)\$/d" file1
$ more +/"dog 123 4335" file1
awk
の場合:
awk 'BEGIN {getline pattern < "other file"}
NR == 1, $0 ~ pattern {next}; {print}' < "input file"
入力がlseekable通常のファイルの場合:
GNU grep
の場合:
{ grep -xFm1 'dog 123 4335' >&2
cat; } <infile 2>/dev/null >outfile
sed
の場合:
{ sed -n '/^dog 123 4335$/q'
cat; } <infile >outfile
GNU grep
が-m
オプション付きで呼び出された場合、一致時に入力が中止され、その(lseekable)入力fdは、見つかったポイントの直後に残ります最後の試合。したがって、grep
w/-m1
を呼び出すと、ファイル内のパターンの最初の出現箇所が検出され、入力オフセットがcat
の正しい場所に正確に残り、ファイル内のパターンの最初の一致に続くすべてがstdoutに書き込まれます。
GNU grep
がなくても、POSIX互換のsed
とまったく同じことができます。sed
q
uitsの場合、入力オフセットをそのままにするように指定されています。 GNU sed
はこのように標準に準拠していないため、GNU sed
を-u
スイッチで呼び出さない限り、上記は機能しません。 。
Awkを使用する1つの方法:
awk 'NR==FNR{a[$0];next}f;($0 in a){f=1}' file2 file1
ここで、file2には検索パターンが含まれています。まず、file2のすべての内容が配列 "a"に格納されます。 file1が処理されると、すべての行が配列と照合され、存在しない場合にのみ出力されます。
2番目のファイルにパターンを保存せずに、件名の質問に対する私の答え。これが私のテストファイルです:
$ cat animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424
deer 2131 213132
bear 2313 21313
GNU sed:
$ sed '0,/^dog 123 4335$/d' animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
Perl:
$ Perl -ne 'print unless 1.../^dog 123 4335$/' animals.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
ファイル内にパターンを持つPerlバリアント:
$ cat pattern.txt
dog 123 4335
$ Perl -ne 'BEGIN{chomp($p=(<STDIN>)[0])};print unless 1../$p/;' animals.txt < pattern.txt
cat 13123 23424
deer 2131 213132
bear 2313 21313
Wth ed
:
ed -s file1 <<< '/dog 123 4335/+1,$p'
これは、1つのp
rintコマンドをhere-stringのedに送信します。印刷コマンドの範囲は1つに制限されます後(+1
)dog 123 4335
ファイルの終わりまで一致($
)。
一時ファイルの作成を気にせず、csplit
を使用できる場合、これは機能します。
sh -c 'csplit -sf"$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2
注file1
は入力ファイルで、file2
はパターンファイルです(質問に記載されています)。
上記のコマンドの長い形式は次のとおりです。
sh -c 'csplit --quiet --prefix="$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2
つまり、
csplit --quiet --prefix="file1_" "file1" "%^$(cat "file2")%+1" && cat "file1_00"
上記のcsplit
フラグなしのprefix
は、ファイルxx00
を作成します(接頭辞はxx
、接尾辞は00
)。上記のフラグを使用すると、ファイルfile1_00
が作成されます。 quiet
フラグがない場合、出力ファイルのサイズ(結果のファイルのサイズ)が出力されます。
Awkは明示的に禁止されていないので、「猫」が一致すると仮定した私のオファリングは次のとおりです。
awk '$0 ~ /cat/ { vart = NR }{ arr[NR]=$0 } END { for (i = vart; i<=NR ; i++) print arr[i] }' animals.txt
マッチした後、ファイルの最後まですべての行を印刷する方法は?
別の言い方をすれば、「一致するまで(最初の行からすべての行を削除する方法)」であり、これはsed
として次のように記述できます。
sed -e '1,/MATCH PATTERN/d'