ITエンジニアの成長ブログ

ITエンジニアとして行う勉強の発信&日々の生活で体験した楽しいことをゆるく発信

Windows標準のコマンドでテキストを検索したい!

あるテキストから特定の文字列を抽出したいシチュエーションはよくあると思います。
Linuxでは便利なgrepコマンドやシェルを駆使して、簡単にやりたいことをやれると思うのですがWindowsではどうやるんだろう?同じようなgrepコマンドあるの?とか何も知らなかったので、今回調査してみました!

Windowsgrepコマンドはあるのか?

まずは何も考えずにgrepコマンドがあるのか、確認してみましょう。コマンドプロンプトを起動して、まずはgrepコマンドを実行してみましょう。
うーん、何となく知ってましたがやはりgrepコマンドはWindowsにはないですね。

f:id:mr_star:20200826001531p:plain
grepコマンドを試す

テキスト検索用のfindコマンドがあるらしい

ネットで色々と検索してはみましたが、grepコマンドはWindows標準では存在しないようです。
代わりと言っては何ですが、特定の文字列をファイルもしくはファイル群から検索することができるfindコマンドというものがあるようです。
実際に使ったことがなかったので、使い方を一から見ていきたいと思います。

findコマンドの使い方

findコマンドの書式は以下の通りです。

書式:find [/V] [/C] [N] [I] [/OFF[LINE]] "文字列" [検索するファイルパス]
※角カッコ([])で囲われているのは、オプションという意味です。指定しなくてもコマンドが動作するということです。

これからこのfindコマンドの使い方を実例でよく使いそうなものに絞って、紹介していきたいと思います。使用するテキストは以下の通りです。
・test.log

2020-08-26 15:02:03.123 INFO 正常に処理が完了しました。
2020-08-26 15:02:04.001 INFO 正常に処理が完了しました。
2020-08-26 15:02:05.034 ERROR エラーが発生しています。
2020-08-26 15:05:01.298 INFO 正常に処理が完了しました。


・test2.log

2020-08-26 15:02:03.123 INFO test Success!
2020-08-26 15:02:04.001 INFO test2 success!
2020-08-26 15:05:01.298 INFO test3 SucCesS!
あるテキストから特定の文字列を含む行を検索したい

書式:find "文字列" 検索するテキストファイルのパス

まずは単純にあるテキストから特定の文字列を含む行を検索してみましょう。
障害対応と仮定して、”ERROR”という文字列を含む行がログに存在するかどうかを確認したい場合などで使います。

>find "ERROR" test.log

---------- TEST.LOG
2020-08-26 15:02:05.034 ERROR エラーが発生しています。
検索した結果にテキストの行番号も表示したい

書式:find /N "文字列" 検索するテキストファイルのパス

今回は前回検索できた内容にさらに情報を付加する目的で、検索するテキストの行番号を合わせて表示したい場合に使えます。
ログファイルがあまりにも大きい場合には、逆にこれがないとどこの情報か分かりづらいので、基本的にこれを使ったほうが良いと思います。

>find /N "ERROR" test.log

---------- TEST.LOG
[3]2020-08-26 15:02:05.034 ERROR エラーが発生しています。

先頭にtest.logの行番号が"[]"角かっこで囲まれて出力されています。
あとオプションは、小文字(/n)でも問題ありません。これは他のオプションでも同様です。

ある特定の文字列を除外して検索したい

書式:find /V "文字列" 検索するテキストファイルのパス

検索の逆のイメージである特定の文字列を含まない行を検索したい場合に有効です。
たとえば、アクセスログなどのログを検索する場合に死活監視のために5秒間隔で同じリクエストがある場合があるかもしれません。
そのような場合には、その5秒間隔のログは基本的には確認しなくてよいものだと思うので、それ以外のログをみたい場合などに便利です。

>find /V "ERROR" test.log

---------- TEST.LOG
2020-08-26 15:02:03.123 INFO 正常に処理が完了しました。
2020-08-26 15:02:04.001 INFO 正常に処理が完了しました。
2020-08-26 15:05:01.298 INFO 正常に処理が完了しました。

指定した文字列”ERROR”を含まない行のみ検索できることを確認できました。
場合によっては使えるオプションだと思います。

ある特定の文字列は大文字・小文字関係なく検索したい

書式:find /I "文字列" 検索するテキストファイルのパス

大文字・小文字関係なく検索したい場合に使えるオプションです。こちらも行番号出力のオプション(/N)と同様に
毎回指定しても問題ないオプションでしょう(というより、そうしたいケースが大半ではと想定します)。

まずはオプション(/I)を指定しない場合を見てみましょう。

>find "success" test2.log

---------- TEST2.LOG
2020-08-26 15:02:04.001 INFO test2 success!

2行目のみ検索されました。デフォルトでは、大文字・小文字を加味して完全一致する行のみが評価されるということです。

オプション(/I)を付与した場合を見てみましょう。

>find /I "success" test2.log

---------- TEST2.LOG
2020-08-26 15:02:03.123 INFO test Success!
2020-08-26 15:02:04.001 INFO test2 success!
2020-08-26 15:05:01.298 INFO test3 SucCesS!

大文字・小文字関係なく文字列として一致するとすべて検索されることがわかりました。

ある特定の文字列を含む行数を検索したい

書式:find /C "文字列" 検索するテキストファイルのパス

ある特定の文字列を含む行をすべて表示するのではなく、行数のみわかればよい場合は本オプション(/C)を指定することで
行数のみ出力することができます。余計な情報はいらないので、とにかく行数のみ分かればよいケースで使用すると良いと思います。

>find /C "ERROR" test.log

---------- TEST.LOG: 1

>find /C "INFO" test.log

---------- TEST.LOG: 3

ファイル名の横に検索した文字列を含む行数を表示します。
対象の文字列に一致した件数ではなく、あくまで行数です(たとえば1行に複数一致する文字列が存在しても、結果は1になります)。

ある特定の文字列を複数のファイルから検索したい

書式:find "文字列" 検索するテキストファイルのパス① 検索するテキストファイルのパス② 検索するテキストファイルのパス・・・

今までは検索する対象のファイルは1つのみでしたが、実は複数指定することができます。指定する場合は、スペース区切りでファイルパスを指定します。

>find "INFO" test.log test2.log

---------- TEST.LOG
2020-08-26 15:02:03.123 INFO 正常に処理が完了しました。
2020-08-26 15:02:04.001 INFO 正常に処理が完了しました。
2020-08-26 15:05:01.298 INFO 正常に処理が完了しました。

---------- TEST2.LOG
2020-08-26 15:02:03.123 INFO test Success!
2020-08-26 15:02:04.001 INFO test2 success!
2020-08-26 15:05:01.298 INFO test3 SucCesS!

一度のコマンド実行で複数のファイルから検索することができました。検索結果も、ファイル別にそれぞれ該当の行が検索できていることが確認できます。
また、上記のようにスペース区切りでいちいち検索したいファイルパスを指定するのではなく、以下のようにワイルドカードで指定ができます。

>find "INFO" *.log

上記の場合はファイル名の末尾に「log」を含むファイルが検索対象となります。

終わりに

色々とオプションなどを紹介していきましたが、いかがでしたでしょうか。
すべて簡単なものなので、問題なく使えると思います。ただし、実際の業務では本コマンドだけでは不十分かもしれません。
たとえば、検索する文字列が多様である場合に正規表現のように指定できないと限界がくるかもしれません。

実は検索する文字列を正規表現で指定できる、findと同じようなコマンドがWindows標準で存在します。
findstrコマンドです。また、別の機会に見ていきたいと思います。
今回も最後までお読みいただきありがとうございました。では、今回はこの辺で。