简体   繁体   中英

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

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

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.

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM