Grepはファイル内のテキストを検索し、テキストの最初の3行を印刷します。

Grepはファイル内のテキストを検索し、テキストの最初の3行を印刷します。

ファイルがあり、ファイル内の複数のファイル名を探しています。検索テキストの例intl_reg.jcl。見つけたら、その上に3行のテキストをインポートする必要があります。たとえば、以下はファイルの4行です。 「残高登録された留学生」という説明 前のテキストは常にCHOICEで、その後に説明が続きます。

CHOICE List registered international students with balances   
SHORTCUT 8  
PROCESS CHDIR /d3/locban/arsys  
PROCESS CMD ksh /d3/locban/arsys/intl_reg.jcl

次のようにリストするには、grepコマンドが必要です。

intl_reg.jcl  registered international students with balances

答え1

使用幸せ(以前のPerl_6)

~$ raku -e 'my @a; for lines() { 
            if @a.elems == 4 { @a.push($_); @a.shift } 
            elsif @a.elems < 4 { @a.push($_) }; 
            if .match( /intl_reg\.jcl/ ) and @a.elems == 4 {
            say $<>.Str, @a[0].split( /<?after List>/ ).[1] }; 
            };' file

つまり、@a配列を宣言してlinesコマンドラインから読み込みます。入力は4になるまで配列に追加され、push最大サイズを4つの要素に維持するために最初の要素が削除されます。@aelemsshift

配列に4つの要素が含まれていることmatchが確認されたら、一致する変数(と同じ)を印刷し、3行前に記録された行を印刷して、必要な文字列を適切に返します。and$<>$<>$/split

入力例:

A CHOICE List registered international students with balances   
A SHORTCUT 8  
A PROCESS CHDIR /d3/locban/arsys  
A PROCESS CMD ksh /d3/locban/arsys/intl_reg.jcl
B CHOICE List registered international students with balances   
B SHORTCUT 8  
B PROCESS CHDIR /d3/locban/arsys  
B PROCESS CMD ksh /d3/locban/arsys/intl_reg.jcl

出力例:

intl_reg.jcl registered international students with balances   
intl_reg.jcl registered international students with balances  

https://raku.org

答え2

次のawkプログラムが動作します。

オプション1:デュアルチャンネル

awk -v d=3 -v s="intl_reg.jcl" '(NR==FNR) && index($0,s){i=FNR;nextfile} 
                                FNR==(i-d){printf "%s\t%s\n",s,$0; exit}' input.txt input.txt

ここでは、入力ファイルを2回指定して2回処理するようにします。検索する文字列がawk変数として渡されs、距離がawk変数として渡されますd

  • 最初のステップでは、NRグローバル行カウンタはFNRファイルごとの行カウンタと同じであり、各行に文字列があるかどうかを確認します。見つかった場合、行番号は変数に保存され、i実行はすぐに次のファイル(=同じファイルの次の繰り返し)にジャンプします。
  • 2番目のパスでは、プログラムは現在の行番号が以前dに認識されたパターン発生回数(に保存されている)より小さいことを確認しますi。その行が見つかると、検索文字列とともに印刷され、プログラムが終了します。ファイル部分の残りの部分をアイドル状態に循環しないようにします。

オプション2:片道

プロセスを高速化してファイルに再度アクセスできない場合(パイプなど)、バッファリングを含むシングルパスソリューションを使用することもできます。この場合、特定の長さの FIFO バッファが必要です。つまり、d大きすぎると実用的ではありません(ただし問題になる場合はほとんどありません)。d

awk -v d=3 -v s="intl_reg.jcl" 'FNR>1{for (j=d;j>0;j--) {buf[j]=buf[j-1]}; buf[0]=$0}
                            FNR>d && match($0,s) {printf "%s\t%s\n",s,buf[d];exit}' input.txt

bufd+1これにより、バッファの内容が各新しい行で「上に移動」し、現在の行は常に最後の数行でバッファを埋めますbuf[0]。検索文字列が見つかると、行の内容が印刷されますbuf[d]。これはd現在の行の前の行です。今回もパフォーマンス上の理由でプログラムは直ちに終了します。

答え3

match=intl_reg.jcl
tac {file} |
    sed -n "/$match/ { n; n; n; s/^CHOICE/$match/p }"

正規表現演算子を$match含めたり含めないでください。/(これは.実際にはワイルドカードなので、このルールをすぐに破棄してください。これは問題になる可能性があります。)

答え4

awkを使用してください。

$ awk -v t='intl_reg.jcl' '{a[NR%4]=$0} index($0,t){$0=a[(NR-3)%4]; $1=$2=""; print t $0}' file
intl_reg.jcl  registered international students with balances

関連情報