1. 概要

Linuxコマンドラインでテキストファイルのいくつかのパターンを検索する場合は、grepコマンドが最初のアイデアになります。

確かに、正規表現の力で、grepはパターンマッチングジョブに優れています。 ただし、指定された行番号の後にあるファイル内のパターンを検索したい場合があります。

このチュートリアルでは、それを実現する方法を探ります。

2. 問題の紹介

いつものように、例を挙げて問題をすばやく理解しましょう。 ログファイルがあるとしましょう:

$ cat -n app.log
     1	[INFO] Application started
     2	[INFO] Invoking remote API ... Successful
     3	[WARN] User "Eric" gave wrong password: 5 times
     4	[ERROR] RuntimeException: File not found: /foo/bar/aFile
     5	... stack trace ...
     6	[INFO] Application refreshed
     7	[ERROR] RuntimeException: File not found: /foo/bar/newFile
     8	... stack trace ...
     9	[WARN] TemplateNotFoundException: Template PRETTY not found, loading the default template
    10	[INFO] Default template loaded
    11	[WARN] Cleanup job done with IOException: Disk is full

上記の出力が示すように、アプリケーションのログファイルがあります。 catコマンドと-nオプションを使用して、行番号付きのコンテンツを表示しました。

「例外」という単語を含むログエントリがいくつかあります。 これらのエントリを検索する場合は、コマンド grep’Exception’app.logを使用するだけです。 それは私たちにとって全く挑戦ではありません。

ただし、追加の要件を追加したいと思います。正確な検索を実行する必要がありますが、6行目以降の行のみを検索します。 つまり、7行目、9行目、および11行目のみが出力に表示されます。

次に、問題を解決する方法を見てみましょう。

3. tailおよびgrepコマンドの使用

この問題を解決するための最初のアイデアは、最初に調べたい行を抽出してから、それらの行に対してgrepを実行することです。

tailコマンド「tail-n+x input」を使用して、x番目の行からファイルの終わりまでの行を取得できます。 したがって、たとえば、6行目からapp.logファイルの最後までの行を抽出できます。

$ tail -n +6 app.log 
[INFO] Application refreshed
[ERROR] RuntimeException: File not found: /foo/bar/newFile
... stack trace ...
[WARN] TemplateNotFoundException: Template PRETTY not found, loading the default template
[INFO] Default template loaded
[WARN] Cleanup job done with IOException: Disk is full

次に、上記の出力で grep コマンドを実行して、必要なログエントリを取得しましょう。

$ tail -n +6 app.log | grep 'Exception'
[ERROR] RuntimeException: File not found: /foo/bar/newFile
[WARN] TemplateNotFoundException: Template PRETTY not found, loading the default template
[WARN] Cleanup job done with IOException: Disk is full

ご覧のとおり、上記のコマンドで問題は解決しました。 予想されるログエントリがあります。

ただし、 grepコマンドを-nオプション付きで実行して、各 matchの行番号を出力したい場合があります。 たとえば、これは「 Exception 」のログエントリを見つけ、スタックトレースを詳しく調べて原因を分析するのに役立ちます。 それでは、-nオプションを指定してコマンドを実行してみましょう。

$ tail -n +6 app.log | grep -n 'Exception'
2:[ERROR] RuntimeException: File not found: /foo/bar/newFile
4:[WARN] TemplateNotFoundException: Template PRETTY not found, loading the default template
6:[WARN] Cleanup job done with IOException: Disk is full

ご覧のとおり、今回は、コマンドは一致した行の行番号を出力しました。 ただし、tailコマンドの出力をgrepにパイプ処理したため、 grepコマンドによって報告された行番号は元の行番号ではありません。入力ファイル

もちろん、この計算によって実際の行番号を取得できます: LINE_NO_BY_GREP + 6 –1。 たとえば、最初に一致する「RuntimeException…」は、app.logファイルの2+6 – 1=7行目にあります。

この計算は機能しますが、大きな入力ファイルで作業している場合は不便になる可能性があります。

次に、元のファイルから実際の行番号とともに、必要な一致した行を取得できるかどうかを確認しましょう。

4. awkコマンドの使用

awk は、コマンドラインテキスト処理のための強力な武器です。 awk コマンドを使用すると、問題を1回で解決できます。

$ awk 'NR >= 6 && /Exception/{ print NR, $0 }' app.log
7 [ERROR] RuntimeException: File not found: /foo/bar/newFile
9 [WARN] TemplateNotFoundException: Template PRETTY not found, loading the default template
11 [WARN] Cleanup job done with IOException: Disk is full

上記のawkコマンドは非常に簡単です。 両方の条件が満たされた場合、行番号とともに行を出力します。

  • NR> = 6 –その行番号は6以上である必要があります。
  • / Exception / –行には「Exception」という単語が含まれている必要があります。

出力で見たように、「Exception」という単語を含む必要な行があります。 さらに、出力の行番号は、app.logファイルの実際の行番号です。

5. sedコマンドの使用

sed は、Linuxでテキストを処理するためのもう1つの便利なコマンドラインユーティリティです。 まず、sedコマンドがどのように問題を解決するかを見てみましょう。

$ sed -n '6,${ /Exception/{=;p} }' app.log
7
[ERROR] RuntimeException: File not found: /foo/bar/newFile
9
[WARN] TemplateNotFoundException: Template PRETTY not found, loading the default template
11
[WARN] Cleanup job done with IOException: Disk is full

出力が示すように、sedは問題を解決しました。 ただし、出力形式は awk で取得したものとは少し異なります。一致した行番号と一致した行は、2つの連続した行にあります。

最後に、コンパクトなワンライナーを見て、それがどのように機能するかを理解しましょう。

  • sed -n –自動印刷を抑制します–つまり、自分で行を印刷するタイミングを制御します
  • 6、$ –6行目からファイルの終わりまでのアドレスを定義します
  • / Exception/{…}–行が上記のアドレスにあり、 / Exception / パターンに一致する場合、{…}アクションが実行されます
  • {=; p} –ここでは、現在の行番号の印刷( = )と現在の行の印刷( p )の2つのアクションを実行します。

6. 結論

この記事では、指定された行番号の後に開始して、ファイル内のパターンを検索する方法について説明しました。

問題を解決するために、例を通じて3つのアプローチに取り組みました。