Jimm Chen
Jimm Chen

Reputation: 3787

Bash, how to check for control character(non-printable character) in a variable?

I have a Bash statement to get user input(a single character) into tmpchar :

read -n 1 -t 1 tmpchar

and I can check for printable character input like this:

if [ "$tmpchar" = "n" ] || [ "$tmpchar" = "N" ]; then
  # do something...
fi

Now my question is: If user input just a Return, or ESC, or Ctrl+a, Ctrl+b etc, how do I check for them?

ENV: openSUSE 12.3 , Bash 4.2.42(1)-release

Upvotes: 1

Views: 4456

Answers (5)

Jimm Chen
Jimm Chen

Reputation: 3787

I find a trick to check for a sole Return input.

if [ "$tmpchar" = "$(echo -e '')" ]; then
  echo "You just pressed Return."
fi

In other word, the highly expected way by @ooga,

if [ "$tmpchar" = $'\x0a' ]; then
  echo "You just pressed Return." # Oops!
fi

does not work for Return anyhow, hard to explain.

Upvotes: 0

kojiro
kojiro

Reputation: 77137

If you want to know if a character isn't a member of the set of printable characters, use a complementary set expression. This seems to work fine with case:

for c in $'\x20' $'\x19'; do
    case "$c" in
        [[:print:]]) echo printable;;
        [^[:print:]]) echo 'not printable';;
        *) echo 'more than one character?';;
    esac
done

(outputs printable and then non printable)

for c in $'\x20' $'\x19'; do
    if [[ $c = [[:print:]] ]]; then
        echo printable
    fi
    if [[ $c = [^[:print:]] ]]; then
        echo not printable
    fi
done

works as well. If you want to know what characters sets your system supports, look at man 7 regex on linux or man 7 re_format on OS X.

Upvotes: 2

perreal
perreal

Reputation: 98078

You can filter the input with tr:

read -n 1 -t 1 tmpchar
clean=$(tr -cd '[:print:]' <<< $tmpchar)
if [ -z "$clean"]; then
    echo "No printable"
else
    echo "$clean"
fi

Upvotes: 0

rici
rici

Reputation: 241861

Use the regex match operator =~ inside of [[ ... ]]:

if [[ $tmpchar =~ [[:cntrl:]] ]]; then
  # It's a control character
else
  # It's not a control character
fi

Note that read -n1 won't do what you expect for a variety of special characters. At a minimum, you should use:

IFS= read -r -n1

Even with that, you'll never see a newline character: if you type a newline, read will set the reply variable to an empty string.

Upvotes: 2

ooga
ooga

Reputation: 15501

Maybe you're looking for ANSI-C quoting. E.g., Ctrl-a is represented as $'\ca'.

Upvotes: 3

Related Questions