开发者

Bash: Variable substitution in quoted string looks like something from the Twilight Zone

I've got a bash script that's reading essentially the output of telnet (actually socat to a unix domain socket).

while read -r LINE; do
    if [ "$USER_DATA_FLAG" == "true" ]; then   #Evaluates to false for the moment
        ...
    else
        printf "%s\n" "Variable> $LINE" >>$DEBUG_LOG
        printf "%s\n" "Line  xxxxz $LINE yxxxxx" >>$DEBUG_LOG
        ...
    fi
done

This yields the following incomprehensible output:

Variable> >INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info
yxxxxxxxxz >INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info
Variable> OpenVPN CLIENT LIST
yxxxxxxxxz OpenVPN CLIENT LIST

The first printf statement works fine and shows exactly what I expect based on my experience at the terminal. But the second printf statement goes nuts, reverses the order of开发者_运维知识库 some the characters and prints $LINE entirely in the wrong place!


$LINE has a \r in it, which is sending the cursor back to column 1. Use parameter substitution or tr to remove it.

$ foo=$'1\r23'
$ echo "$foo"
23
$ echo "${foo/$'\r'/}"
123


This will ramble on a bit. The first thing I noticed was this:

printf "%s\n" "Variable> $LINE" >>$DEBUG_LOG

And I immediately think, "this is C code." In shell programming, printf is somewhat an odd tool which is sometimes useful, unlike the printf in C, which is the first thing you reach for when your printing something out. Try this instead:

echo "Variable> $LINE" >>$DEBUG_LOG

The other problem is potentially with telnet. If you parse telnet output in a shell, you're going to get some characters you don't want -- carriage returns, for example. The default value of IFS for bash is <space><tab><newline>, which will NOT catch carriage returns and the carriage returns WILL mess with the location of characters in your terminal.

Ideally, you would get a proper telnet client and use it non-interactively. However, in a pinch, you can do this:

while tr -d '\r' | read -r LINE; do
    ...

This will strip out carriage returns -- but there could still be other telnet junk in there, including WILL/WONT/DO/DONT commands, and NUL bytes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜