Bash:带引号的字符串中的变量替换看起来像是来自Twilight Zone的东西

时间:2011-07-12 03:25:40

标签: linux bash variables printf

我有一个bash脚本,它基本上读取了telnet的输出(实际上是一个unix域套接字)。

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

这会产生以下难以理解的输出:

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

第一个printf语句工作正常,根据我在终端的经验准确显示我的期望。但第二个printf声明变得疯狂,颠倒了一些角色的顺序,并完全在错误的地方打印$ LINE!

2 个答案:

答案 0 :(得分:3)

$LINE中有一个\r,它将光标发送回第1列。使用参数替换或tr将其删除。

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

答案 1 :(得分:2)

这会稍微絮絮叨叨。我注意到的第一件事是:

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

我立即想,"这是C代码。"在shell编程中,printf有点奇怪,有时候很有用,不像C中的printf,这是你打印出来的第一件事。试试这个:

echo "Variable> $LINE" >>$DEBUG_LOG

另一个问题可能是 telnet 。如果您在shell中解析telnet输出,那么您将获得一些您不想要的字符 - 例如回车。 IFS的{​​{1}}的默认值为bash,它不会捕获回车符,并且回车符会使终端中的字符位置变得混乱。

理想情况下,您将获得一个正确的telnet客户端并以非交互方式使用它。但是,在紧要关头,您可以这样做:

<space><tab><newline>

这将删除回车 - 但那里可能还有其他的telnet垃圾,包括WILL / WONT / DO / DONT命令和NUL字节。