ファイルの最初の行と最後の行を表示するコマンド

ファイルの最初の行と最後の行を表示するコマンド

複数行のファイルがあり、各行の先頭にタイムスタンプがあります。

[Thread-3] (21/09/12 06:17:38:672) logged message from code.....

だから私はいつもこのログファイルで確認することが2つあります。

  1. 最初の数行にはグローバル条件があり、開始時間も提供されます。
  2. 最後の数行には、終了ステータスとその他の情報が含まれています。

ファイルの最初の行と最後の行のみを表示できる、迅速で便利な単一のコマンドはありますか?

答え1

@rushは大きなファイルの場合はhead + tailを使用するのが正しいですが、小さいファイル(20行未満)の場合は一部の行を2回出力できます。

{ head; tail;} < /path/to/file

同様にうまく動作しますが、上記の問題はありません。

答え2

sedまたは、awkコマンドを使用して実行できます。ただし、sedとにかくawkファイル全体を実行する必要があるため、速度が急速に低下します。速度に関しては、毎回tail+を組み合わせるか、関数を生成することをお勧めしますhead。入力がパイプの場合は機能しないという欠点がありますが、シェルがそれをサポートしている場合はプロセス置換を使用できます(以下の例を参照)。

first_last () {
    head -n 10 -- "$1"
    tail -n 10 -- "$1"
}

その後、次のように起動します。

first_last "/path/to/file_to_process"

プロセスの交換を続けます(bash、zsh、kshなどのシェルのみ)。

first_last <( command )

grepPS「グローバル条件」が存在することを確認するために1つを追加することもできます。

答え3

このソリューションは、チャンク単位で読み取るときにあまりにも多くのデータを消費する可能性があり、パイプから検索できない場合はカーソルが範囲外になる可能性があるため、パイプ{ head; tail; }(またはソケットや他の検索できないファイル)では機能しません。headfile そのtail意味が選択されました。

したがって、シェルのように一度に1文字を読み取るツールを使用できますread(ここでは、最初の行と最後の行の数を引数として取る関数を使用します)。

head_tail() {
  n=0
  while [ "$n" -lt "$1" ]; do
    IFS= read -r line || { printf %s "$line"; break; }
    printf '%s\n' "$line"
    n=$(($n + 1))
  done
  tail -n "${2-$1}"
}
seq 100 | head_tail 5 10
seq 20 | head_tail 5

またはawkで実装してくださいtail。たとえば、次のようになります。

head_tail() {
  awk -v h="$1" -v t="${2-$1}" '
    {l[NR%t]=$0}
    NR<=h
    END{
      n=NR-t+1
      if(n <= h) n = h+1
      for (;n<=NR;n++) print l[n%t]
    }'
}

そしてsed

head_tail() {
  sed -e "1,${1}b" -e :1 -e "$(($1+${2-$1})),\$!{N;b1" -e '}' -e 'N;D'
}

(一部のsed実装では、パターン空間のサイズに対する制限が低いため、末尾の行の値が大きいと失敗します。)

答え4

プロセス置換を使用すると、bash次のことができます。

make_some_output | tee >(tail -n 2) >(head -n 2; cat >/dev/null) >/dev/null

行の順序は保証されていませんが、長さが8kBを超えるファイルの場合はそうです。この 8kB カットオフは読み取りバッファの一般的なサイズであり、| {head; tail;}小さなファイルには適用されない理由に関連しています。

これはパイプラインをアクティブにcat >/dev/null保つheadために必要です。それ以外の場合は、tee早期終了が発生し、出力を取得してもtail終了ではなく入力の中間のどこかで発生します。

最後に別の場所>/dev/nullに移動してみてはいかがでしょうか?次の場合:tail|

make_some_output | tee >(head -n 2; cat >/dev/null) | tail -n 2  # doesn't work

headtail標準出力はコンソールの代わりにパイプに移動しますが、これは私たちが望むものではありません。

関連情報