ワイルドカードを含むパイプヘッダーとテール

ワイルドカードを含むパイプヘッダーとテール

同じディレクトリに複数のファイルがあるので、15日から20日までの連続した間隔で特定の行を印刷したいと思います。

単一ファイルの場合は機能しますhead -n20 file.txt | tail -n6が、ワイルドカードパターンで機能させるにはどうすればよいですか?例えば、そのディレクトリ内のすべてのtxtファイルについて*.txt

head -n20 *.txt | tail -n6 # this only crops results of head -n20

編集1:解決策も知っていますが、forワイルドカードでも機能する統合された方法で複数のタスクのパイプラインを定義する方法を学びたいと思います。

psには、wildcards==> file.txt <==と組み合わせるときに提供されるような標準ヘッダーがあるかもしれませんが、これはあまりにも多くを必要とします。headtail

ppsはUbuntuを使用していますが、UNIX全体のアプローチが優れています。

答え1

この一行はどうですか?

for f in *.txt; do echo -e "\n==> $f <=="; head -n 20 "$f" | tail -n 6; done

現在のディレクトリで実行されている場合は、globを使用して.txtすべて*.txtのファイルを繰り返し、ヘッダーを印刷し、各ファイルに対してヘッドとテールを実行します。

答え2

参考にしてください。基準head複数のファイル名を引数として使用し、これらの==> filename <==ヘッダーを出力できます。基準tail1つのファイル名のみを引数として使用できます。複数のファイル名が渡された場合、動作は指定されません。

ここでは、シェルループの代わりに次のコマンドを使用できますgawk

gawk 'BEGINFILE{print sep"==> "substr(FILENAME, 3)" <=="; sep = "\n"}
      FNR >= 15
      FNR == 20 {nextfile}' ./*.txt

これを関数に置き換えることができます。

linerange() (
  min=$1 max=$2
  shift 2
  exec gawk -v min="$min" -v max="$max" -e '
    BEGINFILE{print sep"==> "FILENAME" <=="; sep = "\n"}
    FNR > max {nextfile}
    FNR >= min' -E /dev/null "$@"
)

それから:

linerange 15 20 *.txt

gawk、他の質問と同様に、awkフォームのパラメータはvar=value入力ファイル名ではなく変数割り当てとして扱われます。これは、一部の.txtファイルが正しく機能しない場合(または...foo=bar.txtなどのより迷惑な副作用が発生する可能性があります)を意味します。ARGC=0.txtORS=.txt

最初のケースではプレフィックス./(後で削除する)を使用してこの問題を解決しsubstr(FILENAME, 3)、2番目のケースでは(空のファイル:/ dev / nullを渡しますが、パラメータを使用して-Eも割り当ては処理されません)。-E

関連情報