Image for post
Image for post

Ops Scripting w. Bash: Frequency 2

Tracking Frequency in BASH (Bourne Again Shell): Part II

Like other solutions in these series, I will divide this into to parts:

  • Serial Pipeline: show how to do a pipeline, where list of shells are piped into loop that simply adds to the data structure.

Previous Article

The Problem

The Solutions for the Procedural Way

Solution 1: Collection Loop

In our first solution, we’ll demonstrate the collection loop, which has an auto-splitting facility. The for loop will automatically split text into parts, with the field separator specified by the built in $IFS environment variable. It then iterates through each part, for an environment variable you specify.

Process using Collection Loop
IFS=$'\n'
for LINE in $(cat passwd); do
process_each $LINE
done
IFS=: LINE_ITEMS=($LINE)
SHELL=${LINE_ITEMS[6]}
[[ -z "${SHELL}" ]] || create_shell_entry
if ! [[ -z "${SHELL}" ]]; then
create_shell_entry
fi
(( COUNTS[${SHELL}]++ ))

Solution 2: Conditional Loop with Read

This is the most common approach, where read “will read a line from the standard input and split it into fields” (man page entry).

while read -r LINE; do
process_line $LINE
done < input_file
while IFS=: read -ra LINE_ITEMS; do
SHELL=${LINE_ITEMS[6]}
process_shell_item $SHELL
done
< passwd
[[ -z "${SHELL}" ]] || create_shell_entry
(( COUNTS[${SHELL}]++ ))

Which Solution is better?

For processing files and splitting the string, while read is typically preferred combination simply because it is less work.

Default Field Separator

Reviewing from above, compare these two:

############ for loop way ############
IFS=$'\n'
for LINE in $(cat input_file); do
### process_line ####
done
########### while loop way ###########
while read -r LINE; do
### process_line ####
done < input_file

Alternative Field Separator

And we have these two:

############ for loop way ############
IFS=$'\n'
for LINE in $(cat passwd); do
IFS=: LINE_ITEMS=($LINE)
### process_fields ####
done
########### while loop way ###########
while IFS=: read -ra LINE_ITEMS; do
### process_fields ####
done < passwd

Next Article

The Conclusion

So there you have it, two ways to process files in a procedural way, and use the built-in input field separator to split a line of text.

  • process a file through for VAR in $(cat file); do ...; done loop construction
  • split a string into an Bash array with read -a or with array notation ().
  • associative arrays: creating, referencing, enumerating values and keys
  • arithmetic with (( ))
  • Need to add IFS='\n' when lines themselves need to be further split, unless using read command.

Written by

Linux NinjaPants Automation Engineering Mutant — exploring DevOps, Kubernetes, CNI, IAC

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store