フォルダ内のすべてのファイルの最初の行と最後の行を印刷します。

フォルダ内のすべてのファイルの最初の行と最後の行を印刷します。

file.log.1上書きされたログファイル(など)がたくさんありますfile.log.2。デバイスからローカルコンピュータにコピーすると、元のタイムスタンプが失われました。だから時間順にまとめたいです。問題は、何が最新で、何が最も古いものであるかは必ずしもわからないということです。

私が望むのは、すべてのログが1つのディレクトリにある場合は、次のように印刷することです。

file: file.log.1
first line: [first line that isn't whitespace]
last line: [last line that isn't whitespace]

これを行うにはPythonスクリプトを書くことができますが、可能であればLinux組み込みスクリプトを使用することをお勧めします。 awk/sedのための仕事ですか?それとも、これは実際にスクリプト言語に適していますか?答えが「はい」の場合、awk / sedは何をしますか?

検索でこのawkコマンドを見つけましたが、ファイル名のみを受け入れ、最後の行の内容を印刷します(そして最後に可変数の空白行があるかもしれません)。

awk 'NR == 1 { print }END{ print }' filename

答え1

だから私はsedこの答えが好きです。

for file in file.log.*
do
   echo "file: $file"
   echo -n "first line: "
   cat "$file" | sed -n '/^\s*$/!{p;q}'
   echo -n "last line: "
   tac "$file" | sed -n '/^\s*$/!{p;q}'
done

答え2

awkコマンド:

awk -v OFS=: '
    FNR==1 {
        # the last non-blank line from the previous file
        if (line) {print filename, fnr, line}
        filename=FILENAME
        line=""
        p=0
    } 
    /^[[:blank:]]*$/ {next} 
    !p {
        # the first non-blank line
        print FILENAME, FNR, $0; p=1
    }
    {fnr=FNR; line=$0} 
    END {print filename, fnr, line}
' *

各ファイルについて、ファイル名、行番号、行をコロンで区切って印刷します。

GNU awk v4にはBEGINFILEモードとENDFILEモードがあり、操作が大幅に簡素化されます。

gawk -v OFS=: '
    BEGINFILE {p=0} 
    /^[[:blank:]]*$/ {next} 
    !p {print FILENAME, FNR, $0; p=1}
    {fnr=FNR; line=$0} 
    ENDFILE {print FILENAME, fnr, line}
' *

答え3

努力する:

awk -F'\n' -vRS="" '
  {
    print "file: " FILENAME;
    gsub(/\n[[:blank:]]+|[[:blank:]]+\n/,"");
    print "first line: " $1;
    print "last line: " $NF;
  }
' file.log.*

答え4

何?パールはありませんか?

for file in file.log.*; do 
    echo "FILE: $file"; 
    perl -ne 'if(/\S/){$k++; $l=$_}; 
              print "First line: $_" if $k==1; 
              END{print "Last line: $l\n"}' "$file";  
done

説明する

  • for file in file.log.*file.log.:現在のディレクトリから名前がで始まるすべてのファイルを繰り返し、各ファイルを$file
  • echo "FILE: $file";:ファイル名を印刷します。
  • perl -ne:現在の入力ファイルを1行ずつ読み、(-n)各行を特別なPerl変数として保存し、$_そのファイルから指定されたスクリプトを実行します。-e
  • if(/\S/){$k++; $l=$_}:現在の行が空白以外の文字(\S)と一致する場合は、行を別の名前で保存し、$lカウンタを$k1ずつ増やします。
  • print "First line: $_" if $k==1;:そうであれば、現在の行($_)を印刷します。これにより、空でない最初の行が印刷されます。$k1
  • END{print "Last line: $l\n"}:入力ラインをすべて読み出して実行します。空でないすべての行をとして保存するため、$lファイルの末尾には$l空でない最後の行があります。これで最後の行が印刷されます。

別の方法:

for file in file.log.*; do 
    printf "FILE: %s\nFirst line: %s\nLast line: %s\n\n" \
        "$file" \
        "$(grep -Em 1 '\S' "$file")" \
        "$(tac "$file" | grep -Em1 '\S' )"; 
done

説明する

これは、3つの文字列を印刷するforためにここで使用したのと同じループですprintf。ファイル名と次の2つのコマンドの出力は次のとおりです。

  • grep -Pm 1 '\S' "$file"-E拡張正規表現を有効にして、\S「空白なし」を使用できるようにします。-m1「最初の一致を見つけて終了」を意味します。
  • tac "$file" | grep -Em1 '\S'tacうんカウントダウンcat。ファイルの内容を印刷しますが、最後の行から最初の行まで印刷します。したがって、このコマンドは空でない最後の行を印刷します。

関連情報