Bash: 输出带有空格的变量和字符串重叠

3
我正在寻找变量中的特定行,例如:

echo "$CodeDesc"

0x19 ERASE(6)
0x1A MODE SENSE(6)
0x1B START STOP UNIT
0x1C RECEIVE DIAGNOSTIC RESULTS
0x1D SEND DIAGNOSTIC
0x1E PREVENT ALLOW MEDIUM REMOVAL
0x23 READ FORMAT CAPACITIES
0x24 SET WINDOW

例如,如果我只是在寻找“MODE SENSE(6)”,我会使用grep、awk(还尝试过sed)。
desc="$( grep "0x1A" <<< "$CodeDesc" | awk '{print substr($0, index($0,$2))}' )"

这确实给了我正确的字符串,即“MODE SENSE(6)”,但当我回显它时,一些字符串会重叠。
echo "DESC: \"$desc\""

给我:
  "SC:"MODE SENSE(6)

注意双引号已经移到了开头,DE不见了。

稍后我还将打印同一个变量以及另一个变量:

echo -e "${desc}${code}"

我会期望这样打印出来:
MORE SENSE(6) 0x1A 1

但实际情况是我得到了以下内容:
 0x1a 1NSE(6)

我无法弄清楚这是怎么回事,需要帮助,谢谢。


似乎你在里边有一个CR没有LF。 - Adam Burry
你从哪里获取字符串?如果是从文件中获取的,它可能会包含奇怪的字符。为了将其“清理”,你可以使用 dos2unix 命令。 - fedorqui
2个回答

5
显然,你的$CodeDesc是由以CRLF结尾的行组成的字符串。 grepawk会忠实地保留行末,并且shell的$()替换会剥离最后的LF,使你得到一个仅以CR结尾的字符串。
当CR被打印时,光标移动到行首并且下一个被打印的东西覆盖了原来的内容。
你可以通过向管道中添加| tr -d '\015'来解决这个问题,或者你可以在awk中完成所有操作,包括grep部分:
desc="$(awk '{gsub(/\r/,"")} /0x1A/ {print substr($0, index($0,$2))}' <<< "$CodeDesc")"

1
它看起来比那更奇怪——在我看来,似乎有一个回车符,然后是一个空格,然后是(正常的)换行符。删除回车符可能会或可能不会完全解决问题。此外,Brian 最好先找出这些垃圾字符最初来自哪里。 - Gordon Davisson
1
谢谢你的提示,| tr -d '\015 解决了问题。@Gordon,我最初使用wget获取代码/描述,然后过滤出代码和描述。 - Brian

3

这里不需要使用 awk 和 grep。

Bash 版本 > v4:

declare -A codes

while read -r code desc; do
    codes["$code"]=$desc
done <<< "$CodeDesc"

printf 'DESC: "%s"' "${codes['0x1A']}"

Bash版本小于v4:

while read -r code desc; do
    [[ $code = '0x1A' ]] && printf 'DESC: "%s"' "$desc"
done <<< "$CodeDesc"

谢谢您的回复,吉拉德。我之前没有想到用map,以上的解决方案已经解决了我的问题,所以我接受了它作为答案。 - Brian
非常好的答案。如果我是问题的作者,我会接受你的回复。 - Helio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接