Hello! Welcome to the next lesson in our Advanced Bash Scripting module.
In our last sessions, we built a solid foundation for text processing. You learned to use grep to find lines matching a pattern and sed to perform powerful in-line edits and transformations. We concluded that sed is a master of line-oriented editing, but its model starts to feel clumsy when your data is structured in columns.
Today, we'll master the tool designed for exactly that scenario: awk. Your learning outcome for this lesson is to extract and format structured text data using awk patterns and actions. Think of awk as a programmable, column-aware text processor. It reads data, recognizes fields, and lets you perform complex filtering and formatting operations that are cumbersome with grep or sed. This is an indispensable skill for parsing logs, processing command outputs, and preparing data for reports—all daily tasks in DevOps.
1. The awk Philosophy: Records and Fields
At its heart, awk operates on a simple but powerful model. It processes input one line at a time. Each line is called a record, and by default, each record is split into fields based on whitespace (spaces or tabs).
The basic syntax for an awk command is: awk 'pattern { action }' filename
- Pattern: A condition that determines if the action should be executed for the current record. If omitted, the action runs for every record.
- Action: The command(s) to execute, enclosed in curly braces
{}. If omitted, the default action is to print the entire record (print $0).
Inside the action block, you can access:
$0: The entire record (the full line).$1: The first field.$2: The second field, and so on.$NF: The very last field in the record.
Let's see a simple example. The df -h command gives us disk usage in a columnar format. If we only want to see the filesystem and its mount point, awk is the perfect tool.
df -h | awk '{ print $1, $6 }'
Here, we told awk to take the output from df -h and, for every line, execute the action print $1, $6.
To solidify these core concepts, let's watch a short video that introduces the awk command structure and its record/field processing model.
Text processing using awk command in linux | awk patterns & actions | BEGIN,END,NR,FS,OFS,RS,ORS ...
The video 'Text processing using awk command in linux' from the Pedagogy channel provides a clear, step-by-step introduction to awk's fundamental syntax.
Please watch the first two segments of the video: Basic Structure (00:21 - 01:10): This explains the pattern { action } structure. Records and Fields (01:10 - 03:40): This covers the core concepts of records, fields, and how to access them with $0, $1, $2, etc. Pay close attention to how fields are identified.
For a detailed written explanation of these foundational concepts, the following article is an excellent reference.
Awk Command in Linux with Examples
The article 'Awk Command in Linux with Examples' on Linuxize.com offers a thorough breakdown of how awk works.
Please read the section 'How awk Works', focusing on the subsections 'Records and Fields' and 'Awk Program'. This reinforces the concepts from the video.
2. Filtering Records with Patterns
The true power of awk comes from its ability to apply actions selectively using patterns. This lets you filter records based on complex conditions, going far beyond what grep can do.
There are several types of patterns:
- Regular Expressions: Just like with
grepandsed, you can filter lines that match a regex.
awk '/error/' log.txt - Relational Expressions: You can perform numerical or string comparisons on fields. This is where
awktruly shines.
awk '$9 >= 500 { print $1, $7, $9 }' access.log - Logical Combinations: You can combine patterns with
&&(AND) and||(OR).
awk '$3 == "error" && $5 > 10 { print $0 }' app.log
awk also provides built-in variables that are extremely useful in patterns:
NR: The Number of the current Record (the line number).NF: The Number of Fields in the current record.
A common use case is skipping the header line in command output: awk 'NR > 1 { print $1 }'.
The image below shows several practical examples of filtering the output of df -hT using different relational patterns.
This next video segment demonstrates how to use these different pattern types to filter data effectively.
Text processing using awk command in linux | awk patterns & actions | BEGIN,END,NR,FS,OFS,RS,ORS ...
Let's return to the Pedagogy video to see how to implement filtering with patterns.
Watch the segment on Using Regular Expressions and Conditions (03:40 - 08:33). Focus on how awk uses regex, the ~ operator for matching patterns in specific fields, and standard comparison operators like > and ==.
3. Formatting Output with Actions
Once you've filtered the records you want, the action block lets you control the output format precisely.
Custom Field Separators
By default, awk uses whitespace as the input field separator. For other formats like CSV files or /etc/passwd, you need to specify the delimiter.
- Use the
-Fcommand-line option:awk -F':' '{ print $1, $7 }' /etc/passwd - Set the
FS(Field Separator) variable, often in aBEGINblock.
You can also control the output field separator using the OFS variable. This is great for converting data from one format to another, for example, from a colon-delimited file to a tab-separated one.
# Read a colon-delimited file, print fields 1 and 7 separated by a tab
awk 'BEGIN { FS=":"; OFS="\t" } { print $1, $7 }' /etc/passwd
Special BEGIN and END Patterns
awk has two special patterns that are invaluable for formatting and reporting:
BEGIN: The action in aBEGINblock is executed once before any records are read. This is the perfect place to initialize variables (likeFSandOFS) or print a header for your output.END: The action in anENDblock is executed once after all records have been processed. This is ideal for printing summaries, totals, or averages.
Here is a classic example: calculating the total size of files from an ls -l output.
ls -l | awk 'NR > 1 { sum += $5 } END { print "Total size:", sum, "bytes" }'
NR > 1: We skip the header line.{ sum += $5 }: For each file line, we add the value of the 5th field (size) to oursumvariable.END { ... }: After all lines are processed, we print the final sum.
The following video segment explains these special blocks and variables in detail.
Text processing using awk command in linux | awk patterns & actions | BEGIN,END,NR,FS,OFS,RS,ORS ...
This final clip from the Pedagogy video covers the BEGIN and END blocks, along with crucial built-in variables like NR, NF, and the separator variables.
Watch the segments covering: BEGIN and END blocks (08:33 - 11:52): Understand how to run code before and after processing. Built-in variables NR, NF (11:52 - 13:50): See how to get line numbers and field counts. Separator variables FS, OFS, RS, ORS (13:50 - 17:31): Focus on FS and OFS for changing input and output delimiters.
4. Practical Scenario: Analyzing a Web Server Log
Let's put everything together in a common DevOps task: Find the top 5 IP addresses generating 500 errors in an Nginx access log.
A typical Nginx log line looks like this:192.168.1.101 - - [15/Oct/2023:10:30:05 +0000] "GET /api/v1/users HTTP/1.1" 500 128 "-" "curl/7.68.0"
The IP address is the 1st field ($1) and the HTTP status code is the 9th field ($9).
Our strategy will be a pipeline:
- Use
awkto filter for lines where the status code is 500 and print only the IP address. - Pipe the list of IPs to
sort. - Pipe the sorted list to
uniq -cto count the occurrences of each IP. - Pipe that to
sort -nrto sort numerically in reverse order (highest count first). - Pipe to
head -5to get the top 5.
Here's the command:
awk '$9 == 500 { print $1 }' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -5
This single line of code demonstrates the power of combining awk's field-based filtering and extraction with other standard Unix tools to quickly generate insightful reports. The Youstable.com blog post has more one-liners like this that are extremely useful in day-to-day operations.
Awk Command Explained With Practical Examples
The article 'Awk Command Explained With Practical Examples' on Youstable.com is full of useful, real-world examples for DevOps engineers.
Skim the following sections for practical inspiration: Getting Started: Essential awk Examples: Look at 'Print Columns and Reorder', 'Filter Rows', and especially 'Count Unique Values and Frequencies', which is very similar to our log analysis example. Work With CSV and Custom Delimiters Use BEGIN and END Blocks
Conclusion
You've now learned how awk bridges the gap between simple line filtering (grep) and line editing (sed) by providing a powerful framework for processing structured, columnar data. This is a huge step forward in your command-line toolkit.
Key Takeaways:
awkprocesses text using apattern { action }model on records (lines) and fields (columns).- Fields are accessed via
$1, $2, ..., $NF, and the whole line is$0. - Patterns filter records using regular expressions, relational comparisons (
$3 > 10), and logical operators (&&,||). - Actions format output using the
printstatement and variables likeOFS(Output Field Separator). - The
-Foption andFSvariable are used to handle non-whitespace delimiters like commas or colons. BEGINandENDblocks are essential for adding headers and summaries to your output.
Preview of the Next Lesson:
We've spent a lot of time using external tools like grep, sed, and awk to manipulate text. However, the Bash shell itself has powerful, built-in capabilities for string manipulation. In the next lesson, we will dive into Bash parameter expansion, learning how to perform slicing, substitution, and case modification directly within the shell, which can be faster and more efficient for certain tasks.