1. Overview

Iterating over each character within a string is a fundamental operation in Bash scripting for processing and manipulating text-based data.

In this tutorial, we’ll learn how to perform a loop through each character in a string in Bash.

First, we’ll look at the parameter expansion method to iterate over the string. After that, we’ll discuss the seq command to get each character in the string. Next, we’ll use the sed editor to achieve the same. Lastly, we’ll learn how to use expr to iterate through string characters.

2. Using Parameter Expansion With for Loop

A basic way to perform a loop for each character in a string uses parameter expansion within a for loop.

2.1. Bash-style for Loop

Parameter expansion is a method to transform the contents of variables. The basic form of parameter expansion is ${parameter}. We substitute parameter with the variable we want to manipulate.

Here, we’ll use parameter expansion to count the number of characters in the string as well as extract a subset of one character.

First, we’ll look at the script parameterExpansion.sh using the cat command:

$ cat parameterExpansion.sh
#!/bin/bash
string="Hello, World!"
length=${#string}
for ((i = 0; i < length; i++)); do
    char="${string:i:1}"
    echo "Character at position $i: $char"
done

In this script, we use the variable string as our initial input. To begin with, we assign the number of characters in string to another variable length. That becomes the stopping condition in the for loop.

After that, we iterate over each character in the string using the char=”${string:i:1}” expression inside a loop:

  • string is the variable to process
  • :i refers to an offset which means the starting position
  • :1 specifies the length we want to extract

In other words, we pick exactly 1 character from the string starting at position i. In addition, we use the echo command to output the extracted character with its position.

Now, let’s make the file executable using the chmod command and execute it:

$ chmod +x parameterExpansion.sh
$ ./parameterExpansion.sh
Character at position 0: H
Character at position 1: e
Character at position 2: l
Character at position 3: l
Character at position 4: o
Character at position 5: ,
Character at position 6:
Character at position 7: W
Character at position 8: o
Character at position 9: r
Character at position 10: l
Character at position 11: d
Character at position 12: !

Thus, we’re able to iterate over each character in a string.

2.2. Basic for Loop With seq

Alternatively, we can use the seq command with the for loop to generate a sequence of numbers from the first index to the highest valid index of the string.

We’ll modify the above script to include seq in the for loop:

$ cat parameterExpansion.sh
#!/bin/bash
string="Hello, World!"
for i in $(seq 0 $((${#string} - 1))); do
    char="${string:i:1}"
    echo "Position $i: $char"
done

In this code, we used seq with parameter expansion inside the for loop to iterate over each character in a string:

  • ${#string} calculates the length of the variable string
  • $((${#string} – 1)) subtracts 1 from the length of the string to get the highest value index as Bash uses zero-based indexing for arrays and strings
  • seq 0 $((${#string} – 1)) generates a sequence of numbers from 0 to the last index of the string, in this case, it generates the index from 0 till the length of the string minus 1

Consequently, the for loop iterated over the sequence of numbers generated by seq. In each iteration, the variable i was set to the next number in the sequence. Inside the loop, the char variable is set to the character at the current position, and the character’s position is displayed.

3. Using the sed Editor

Another approach to traverse over each character in the string is to use the sed editor with a loop.

In this method, we’ll use sed with its substitution option to convert a string into an array. To elaborate further, we’ll utilize the pattern-matching functionality of sed.

In addition, we’ll separate the array using the space character. Lastly, we’ll use a loop to iterate over the array elements.

Let’s start by looking at the iterateUsingSed.sh script:

$ cat iterateUsingSed.sh
#!/bin/bash
str="Hello, World!"
chars=($(echo "$str" | sed 's/./& /g'))
for ((i=0; i<${#chars[@]}; i++)); do
     echo "Character at position $i: ${chars[i]}"
done

In this script, we used chars=($(echo “$str” | sed ‘s/./& /g’) to split the str contents into an array. First, we piped the output of str to the sed stream editor. After that, we used the s/./& /g regular expression:

  • s/ denotes substitution operation
  • ./ pattern matches any character in the string
  • & is a special replacement that represents the matched character
  • /g indicates the global operation

Lastly, we used chars=(…) to capture the final output and store it in the array char.

We’ll make the file executable to view the output:

$ chmod +x iterateUsingSed.sh
$ ./iterateUsingSed.sh
Character at position 0: H
Character at position 1: e
Character at position 2: l
Character at position 3: l
Character at position 4: o
Character at position 5: ,
...

To conclude, we traversed the string by taking its contents, processing it using sed to insert a space after each character, and storing it as an array. We’re performing this step to separate the characters in the output, so they can get assigned to sequential array elements. Thus, it becomes easier to print the characters in the subsequent for loop.

4. Using the expr Utility

The last approach for this guide is to use the expr utility to traverse through the characters in a string.

Although we mostly use expr for arithmetic operations, we can also use it for string manipulation, extraction, and pattern matching.  In our scenario, we’ll use it to extract substrings.

Let’s view the exprString.sh script:

$ cat exprString.sh
#!/bin/bash
str="Hello, World!"
for ((i=0; i<${#str}; i++)); do
    char=$(expr substr "$str" $((i + 1)) 1)
    echo "Character at position $i: $char"
done

Since expr doesn’t provide an easy way to iterate through characters in a string, we again use the for loop. Inside the loop block, we use char=$(expr substr “$str” $((i + 1)) 1):

  • expr evaluates the expression written after the command
  • substr is an expr function that extracts a substring from a string
  • “$str” is the input string from which we want to retrieve a character
  • $((i + 1)) is an arithmetic expression that specifies the starting position for the substring
  • 1 specifies the length of the substring
  • char=$(expr …) stores the output of the entire expression which is the extracted character

To summarize, we extracted each character from str using expr substr from its position and printed it using a for loop:

$ chmod +x exprString.sh
$ ./exprString.sh
Character at position 0: H
Character at position 1: e
Character at position 2: l
Character at position 3: l
Character at position 4: o
Character at position 5: ,
...

Thus, the expr utility enabled us to iterate through each character in str.

5. Conclusion

In this article, we discussed how to loop through each character in a string in Bash.

First, we looked at parameter expansion to access each character in a string. After that, we discussed the seq command to traverse through characters in a string. We also discussed how to use sed and arrays together to get each character in the string. Lastly, we discussed how we can use expr for our purposes.