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



9 comment
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 :)
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"
Ohh! You could ALSO, include aplay atinysound.wav after the echo line, so you get that uber-cool sound when text prints.
hi
the tutorial was very good and usefull
thank you in advance
Amir from Iran
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
Yes, my mistake :)
when the variable
IFS=
is set empty as above then spaces can be red succssfully.
Cheers
Luk
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.
Would it then be slightly faster to do this ?
Problems if the input is console instead of file:
#!/bin/bash
INPUT=/dev/tty1
while IFS= read -r -n1 char
do
echo “===$char===”
done < "$INPUT"