助け合いフォーラム
正解
grep -E '17:[0-9]+:[0-9]+' system.log
grep -E '17:[0-5][0-9]:[0-5][0-9]' system.log
解説
grepコマンドの書式は以下のとおりです。拡張正規表現を使用する場合は「-E」オプションを使用します。
grep [オプション] 検索パターン [ファイル名]
以下は主な正規表現とその使用例をまとめたものです。
17時台のログは「17:00:00」から「17:59:59」の範囲の時刻です。
選択肢を1つずつ確認します。
・grep -E '17:[0-9]+:[0-9]+' system.log
[0-9]は0~9のいずれかの数字を表し、「+」は直前の文字の1回以上の繰り返しなので、「17:0:0」から「17:99:99」の範囲を抽出します。結果として17時台のログは抽出されるので、正しいコマンドです。
・grep -E '17:[0-9]?:[0-9]?' system.log
「?」は直前の文字の0回もしくは1回の繰り返しなので、「17::」や「17:9:9」のような行を抽出します。17時台のログは抽出されませんので、誤りです。
・grep -E '17:[0-59]:[0-59]' system.log
[0-59]は0~5,9のいずれかの数字を表すので、「17:0:0」や「17:2:4」のような行を抽出します。17時台のログは抽出されませんので、誤りです。
・grep -E '17:00|59' system.log
「17:00|59」は「17:00」か「59」のいずれかの文字列を抽出します。17時台のログは抽出されませんので、誤りです。
・grep -E '17:[0-5][0-9]:[0-5][0-9]' system.log
[0-5]は0~5のいずれかの数字、[0-9]は0~9のいずれかの数字を表すので、「17:00:00」から「17:59:59」の範囲を抽出します。17時台のログは抽出されるので、正しいコマンドです。
したがって正解は
・grep -E '17:[0-9]+:[0-9]+' system.log
・grep -E '17:[0-5][0-9]:[0-5][0-9]' system.log
です。
以下は実行例です。赤い部分がgrepコマンドにマッチした文字列です。
参考
以下は主な正規表現とその使用例をまとめたものです。
正規表現には次のような基本の概念があります。
・特殊文字
「|」や「\(エスケープ文字)」などのように特殊な意味を持つ文字のことです。
・文字クラス
「[ ]」内の文字集合のことです。
・数量詞
「*」や「+」などのように直前の文字の繰り返し回数を示す文字のことです。
・アンカー
「^」や「$」などのように文字列内での位置を示す文字のことです。
なお、正規表現の「*」と、シェルによって解釈されるメタキャラクタの「*」では意味が異なるので注意してください。シェルは「*」を0文字以上の文字列と解釈します。
正規表現は明示的に「'」(シングルクォーテーション)や「"」(ダブルクォーテーション)の引用符で囲う事ができます。これらの引用符で囲まれた正規表現の記号は、シェルにメタキャラクタとして扱われなくなります。
正規表現を利用する主なコマンドは以下のとおりです。
・grep
ファイルや標準入力から、検索パターンにマッチする文字列を含む行を抽出するコマンド
なお、「-E」オプションを併用すると拡張正規表現が使えます(egrepコマンドと同様)。
・sed
ファイルや標準入力の内容を編集して表示するコマンド
例1)1から5までのいずれかの文字がある行を「test.txt」ファイルから抽出する場合
$ grep '[1-5]' test.txt
例2)「test.txt」ファイルの「#」から始まる行を削除して出力する場合
$ sed '/^#/d' test.txt
基本正規表現と拡張正規表現の違いに注意してください。grepコマンドは、-Eオプションを付けないと検索パターンを基本正規表現と判断しますので、上表の拡張正規表現が使えません。
実行例)
基本正規表現では「?, +」は「\?, \+」とすることで、拡張正規表現と同様の意味を持つようになります。
[grep -E '17:[0-9]+:[0-9]+' system.log]の選択肢について
+は「直前の文字を1回以上繰り返し」なので、17:00:11、17:11:44、17:33:55のような時刻しか表現できず、17:12:45、17:41:21のような時刻は表現できないので不正解だとおもうのですが、なぜ正解なのでしょうか
例1)1から5までのいずれかの文字がある行を「test.txt」ファイルから抽出する場合
$ grep '[1-5]' test.txt
1から5までのいずれかの文字
[1-5]
0から9までのいずれかの文字
[0-9]
△から△までの範囲のいずれかの文字
[ △ - △ ]
いずれかの文字を出すを繰り返すからでは?
0から9の範囲の1文字のいずれかを
繰り返す。
[0-9]が 0 のとき + で 0
ではなく
[0-9]の範囲のどれか1つ
を直前の文字として、1回以上繰り返す。のでは?
[0-9]かとが 0 なので
+は「直前の文字を1回以上繰り返し」だから、もう一回、0 ではなく
直前の[0-9] が 0 だったけども
- は
直前の文字を1回以上繰り返し
は
直前に出た 0 をもう1回繰り返す
のではく
直前に行った [0-9] 0から9の範囲のうちの1つの数字を出す、という事をもう一回繰り返す。
grep -E '17:[0-9]+:[0-9]+' system.log
コメント
[ 0 - 9 ] [ 0 - 9 ] : [ 0 - 9 ] [ 0 - 9 ]
を拡張正規表現の + を使用して、記述を短くしている。
[ 0 - 9 ] + : [ 0 - 9 ] +
[ 0 - 9 ] が [ 0 ]でも、次の[ 0 - 9 ]は前の[ 0 ]とは関係なく、[ 0 - 9 ]で0~9のいずれか
[ 0 - 9 ] と [ 0 - 9 ]
0 と 1
1 と 2
4 と 5
あくまでも[ 0 - 9 ]の範囲に含まれているどれか1つの文字列を2回、別々に出している。
コメント
この投稿に対して返信しませんか?