Bash Script: Read One Character At A Time

by on September 30, 2009 · 7 comments· LAST UPDATED September 30, 2009

in , ,

I need to count one character at a time from input.txt. How do I read one character at a time under Linux / UNIX bash shell script?

The read builtin can read one character at a time and syntax is as follows:

 
read -n 1 c
echo $c
 

You can setup the while loop as follows:

#!/bin/bash
# data file
INPUT=/path/to/input.txt
 
# while loop
while IFS= read -r -n1 char
do
        # display one character at a time
	echo  "$char"
done < "$INPUT"

Example: Letter frequency counter shell script

#!/bin/bash
INPUT="$1"
# counter 
a=0
b=0
cc=0
 
# Make sure file name supplied
[ $# -eq 0 ] && { echo "Usage: $0 filename"; exit 1; }
 
# Make sure file exits else die 
[ ! -f $INPUT ] && { echo "$0: file $INPUT not found."; exit 2; }
 
# the while loop, read one char at a time
while IFS= read -r -n1 c
do
	# counter letter a, b, c
	[ "$c" == "a" ] && (( a++ ))
	[ "$c" == "b" ] && (( b++ ))
	[ "$c" == "c" ] && (( cc++ ))
done < "$INPUT"
 
echo "Letter counter stats:"
echo "a = $a"
echo "b = $b"
echo "c = $cc"

Run it as follows:
/tmp/readch /etc/passwd
Sample outputs:

Letter counter stats:
a = 169
b = 104
c = 39

See also:

TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 7 comments… read them below or add one }

1 lefty.crupps October 1, 2009 at 12:27 pm

How about a script which runs Bash for me, but its output is slow, one-letter-at-a-time old school terminal looking? For example, when I run this script I am returned to a bash prompt; I run ”ls’ and the returning text is written as a single character every 1/2 second or so.

Useless but I think it sounds retro and fun :)

Reply

2 DougTheBUg July 23, 2010 at 11:45 pm

I don’t know about doing that with bash, but I think it would be cool for log files.

#!/bin/bash
# data file
INPUT=/var/log/messages

# while loop
while IFS= read -r -n1 char
do
# display one character at a time
echo -n “$char”
sleep .05
done < "$INPUT"

Reply

3 DougTheBUg July 23, 2010 at 11:46 pm

Ohh! You could ALSO, include aplay atinysound.wav after the echo line, so you get that uber-cool sound when text prints.

Reply

4 amir May 23, 2012 at 8:59 pm

hi
the tutorial was very good and usefull
thank you in advance
Amir from Iran

Reply

5 Luksz April 3, 2014 at 4:32 pm

Hello Guys,
This is great information covered here.
When I try these examples all works perfectly except I cannot read space or tab as a character, instead I have empty $c variable.
Do you know how to improve it to have the possiblity to read all characters including spaces and tabs?
Cheers
luk

Reply

6 Luksz April 3, 2014 at 4:40 pm

Yes, my mistake :)
when the variable
IFS=
is set empty as above then spaces can be red succssfully.
Cheers
Luk

Reply

7 Meow October 19, 2014 at 7:25 am

The way using `read -r -n1` for reading every character is wrong, it can’t handle multi-byte characters.

You should handle the characters in this way:

string=”Hello world, 你好世界”
for (( i = 0; i < ${#string}; i++ )); do
c="${string:i:1}"
echo $c
# process every characters.
done

The downside is the performance is not pretty good if your string is very long.

Reply

Leave a Comment

Tagged as: , , , , , , , , , , ,

Previous Faq:

Next Faq: