ruby
20 lines · 6 steps
Parsing Apache logs with named captures
A regex with named groups turns each raw Apache access-log line into a clean, typed Ruby hash.
Explained by
highlit
1class ApacheLogParser
2 LINE_PATTERN = /\A(?<ip>\S+)\s\S+\s\S+\s\[(?<time>[^\]]+)\]\s"(?<method>[A-Z]+)\s(?<path>\S+)\s(?<protocol>[^"]+)"\s(?<status>\d{3})\s(?<bytes>\d+|-)/
3
4 TIME_FORMAT = "%d/%b/%Y:%H:%M:%S %z"
5
6 def parse(line)
7 match = LINE_PATTERN.match(line)
8 return nil unless match
9
10 {
11 ip: match[:ip],
12 timestamp: DateTime.strptime(match[:time], TIME_FORMAT),
13 method: match[:method],
14 path: match[:path],
15 protocol: match[:protocol],
16 status: match[:status].to_i,
17 bytes: match[:bytes] == "-" ? 0 : match[:bytes].to_i
18 }
19 end
20end
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Named capture groups make a complex regex self-documenting and let you pull fields by meaning instead of positional index.
- 2Returning nil on a failed match keeps parsing tolerant of malformed lines instead of crashing.
- 3Raw text fields should be coerced to real types at the boundary so downstream code works with integers and dates, not strings.
Related explainers
ruby
require "shellwords" require "open3" module Backup
Building safe shell commands in Ruby
shell-out
subprocess
command-injection
Intermediate
7 steps
ruby
class UserAgentParser BROWSERS = [ [/Edg\/([\d.]+)/, "Edge"], [/OPR\/([\d.]+)/, "Opera"],
Parsing user-agent strings in Ruby
regex
pattern-matching
lookup-tables
Intermediate
8 steps
javascript
function evaluate(expression) { const tokens = tokenize(expression); let pos = 0;
Building a recursive descent calculator
parsing
recursion
operator-precedence
Intermediate
8 steps
ruby
class LogAggregator BUCKET_FORMAT = "%Y-%m-%dT%H:%M" def initialize(entries)
Bucketing log entries by the minute in Ruby
aggregation
hashing
enumerable
Intermediate
5 steps
ruby
class WeeklySignupsReport DEFAULT_WEEKS = 12 def initialize(weeks: DEFAULT_WEEKS, source: User.all)
Building a weekly signups report in Rails
service object
aggregation
group by
Intermediate
7 steps
rust
use chrono::{Duration, NaiveDate}; #[derive(Debug)] pub struct DateRange {
Parsing and iterating date ranges in Rust
error-handling
iterators
parsing
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/parsing-apache-logs-with-named-captures-explained-ruby-8f54/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.