パターンが存在しない限り、ファイルからパターンまで行を削除します。

パターンが存在しない限り、ファイルからパターンまで行を削除します。

sed次のようなものを使用するか、次のようにしてawkフィルタを作成しようとします。

  • 与えられたパターンが入力にない場合、入力全体を出力にコピーします。
  • パターンが入力に存在する場合、最初の発生後の行のみが出力にコピーされます。

これは "git clean"フィルタと連携しますが、おそらく重要ではありません。重要な点はこれです必要stdinで入力が提供されるため、フィルタとして実装されます。

sedたとえば、特定のパターンの行を削除する方法を知っています。ただし、どこにも一致するものがない場合は、1,/pattern/d入力全体が削除されます。/pattern/

grep -q一時ファイルを作成し、操作を実行し、入力で何をするかを決定する完全なシェルスクリプトを作成することを想像できます。可能であれば、一時ファイルを作成せずにこれを行うことをお勧めします。 gitが頻繁に呼び出すことができるので、効率的でなければなりません。

ベストアンサー1

ファイルが大きすぎてメモリに収まらない場合は、Perlを使用してファイルを読み取ることができます。

perl -0777pe 's/.*?PAT[^\n]*\n?//s' file

PAT希望のモードに変更するだけです。たとえば、次の2つの入力ファイルとスキーマがあるとします5

$ cat file
1
2
3
4
5
11
12
13
14
15
$ cat file1 
foo
bar
$ perl -0777pe 's/.*?5[^\n]*\n?//s' file
11
12
13
14
15
$ perl -0777pe 's/.*?10[^\n]*\n?//s' file1
foo
bar

説明する

  • -pe:入力ファイルを1行ずつ読み込み、与えられたスクリプトを-e各行に適用して印刷します。
  • -0777:ファイル全体をメモリに保存します。
  • s/.*?PAT[^\n]*\n?//s:最初に表示されるまで、PAT行末まですべてを削除します。

大きなファイルの場合、ファイルを2回読み取ることを避ける方法はありません。それは次のとおりです。

awk -vpat=5 '{
              if(NR==FNR){
                if($0~pat && !a){a++; next} 
                if(a){print}
              }
              else{ 
                if(!a){print}
                else{exit} 
              }
             }' file1 file1

説明する

  • awk -vpat=5:実行しawkて変数patをに設定します5
  • if(NR==FNR){}:最初のファイルの場合。
  • if($0~pat && !a){a++; next}:行が値と一致し、pat定義されてaいない場合は、a行を追加して次の行に移動します。
  • if(a){print}a定義されている場合(ファイルがパターンと一致する場合)、行を印刷します。
  • else{ }:最初のファイルではない場合(したがって2番目のパスです)。
  • if(!a){print}定義されていない場合はaファイル全体が必要なため、すべての行が印刷されます。
  • else{exit}a定義されている場合は、最初のステップですでに印刷されているため、ファイルを再処理する必要はありません。

おすすめ記事