この記事は何
shellgei160を通じて言語習得 Advent Calendar 2023に参加しています。
書籍「シェル芸ワンライナー160本ノック」の例題をRubyで解いてみて、Rubyの学習に役立てようとするものです。
例題はこちらのリポジトリで公開されているものに限ります。
https://github.com/shellgei/shellgei160
実行環境など
- Docker image: ruby:3.0.2
- 上記リポジトリをクローンした上で、リポジトリのルートディレクトリ直下に
answer-ruby
ディレクトリを作り、その中に解答となるファイルを作成していきます。
今回のテーマ
$ cat log_range.log | sed -n '/24\/Dec\/2016 21:..:../,/25\/Dec\/2016 03:..:../p'
時間順にソート済みのログファイルに対し、開始日時にマッチした行から、終了日時にマッチした行までを抽出します。sed
の使い方の勉強になりますね。
解
re_start = %r{24/Dec/2016 21:..:..}
re_end = %r{25/Dec/2016 03:..:..}
records = File.readlines('qdata/9/log_range.log')
idx_start = records.index { |record| record.match(re_start) }
idx_end = records.index { |record| record.match(re_end) }
puts records[idx_start..idx_end]
愚直に指定した文字列にヒットするインデックスを調べ、その範囲を抽出しました。
もし関数型っぽくやるなら、(left, matched, right)みたいにログを分割する関数を作って、startの方で (matched, right) を残し、その結果に対してendの方で (left, matched) を残す、とかでも良さそうです。
所感
- 条件に合うインデックスを探すには
array.index {block}
。なるほど。 - メタ文字を含む正規表現には
%r{ }
が便利。なるほど。※{
じゃなくても@
とか他の記号でも良い。