如何从$()
bash 中获得未修改的输出?
我需要让 bash 返回命令替换的结果(通过$(command)
或`command`
),但 bash 将左方括号视为test
内置并评估文本。
> echo "This shows an IP in brackets [127.0.0.1] when not in the command substitution context."
This shows an IP in brackets [127.0.0.1] when not in the command substitution context.
> echo $(echo "This should show an IP in brackets [127.0.0.1] but instead evaluates to '1'.")
This should show an IP in brackets 1 but instead evaluates to '1'.
> echo $(echo "The subtle addition of a space causes [127.0.0.1 ] to behave differently.")
The subtle addition of a space causes [127.0.0.1 ] to behave differently.
背景
请注意,使用echo
上面提供的最小示例就是这样;我的最终用途将包括来自该主机的输出ping
或tracert
显示该主机所看到的主机的IP(即尊重任何主机条目)。在这种用法中,我几乎无法控制命令输出的字符串。
> grep -E "^[^#].*stackoverflow" /c/Windows/System32/drivers/etc/hosts
127.0.0.1 stackoverflow.com
> tracert -h 1 -w 1 stackoverflow.com | awk '/Tracing/'
Tracing route to stackoverflow.com [127.0.0.1]
> ping -n 1 -w 1 stackoverflow.com | awk '/Pinging/'
Pinging stackoverflow.com [127.0.0.1] with 32 bytes of data:
# Using dig or nslookup would show a real IP rather than the forced IP from the hosts entry.
> dig @ns1 +nocmd stackoverflow.com +noall +answer
stackoverflow.com. 118 IN A 151.101.129.69
stackoverflow.com. 118 IN A 151.101.193.69
stackoverflow.com. 118 IN A 151.101.1.69
stackoverflow.com. 118 IN A 151.101.65.69
> echo $(ping -n 1 -w 1 stackoverflow.com | awk '/Pinging/')
Pinging stackoverflow.com 1 with 32 bytes of data:
> echo $(ping -n 1 -w 1 stackoverflow.com | awk '/Pinging/ {print $3}')
1
> ping -n 1 -w 1 stackoverflow.com | awk '/Pinging/ {print $3}'
[127.0.0.1]
答案1
问题是命令替换本身没有被引用。当命令替换使用命令的输出echo
作为第二个命令的参数时echo
,命令结果会受到单词分割和文件通配的影响。正如注释中所指出的,方括号内的字符将匹配名称恰好是一个字符并且是、、或[127.0.0.1]
之一的任何文件(该模式仅匹配shell,忽略和目录链接)。当我创建一个名为的文件时,我可以复制您的结果。1
2
7
0
.
.
..
1
为了避免命令替换的结果受到通配符的影响,您应该将其用双引号引起来:
echo "$(echo "This will show an IP address in square brackets: [127.0.0.1]")"
另请参阅 Greg's Wiki 中的以下相关文章(特别是第一篇,其中涵盖了命令替换内部和外部双引号的需要):