在带引号的字符串中使用bash set命令

问题描述

我正在尝试解析一系列包含值和字符串混合的输出行。 我认为set命令将是一种简单的方法

初步测试似乎很有希望。这是示例命令行及其输出

$ (set "one two" three; echo $1; echo $2; echo $3)
one two
three

很明显,我得到了两个变量,而第三个变量却什么也没有。

但是,当我将其放在脚本中(使用read捕获输出行)时,会得到另一种解析:

echo \"one two\" three |
while read Line
do
    echo $Line
    set $Line
    echo $1
    echo $2
    echo $3
done

这是输出

"one two" three
"one
two"
three

echo $Line命令显示引号在那里,但是set命令不使用引号来分隔参数。为什么不呢?

在研究readwhile read用法时,我遇到了while IFS= read这个习惯用法,因此我尝试了一下,但没有任何区别。

我已经阅读了许多有关报价的问题,但没有发现任何可以为我澄清的问题。显然,我的报价水平很混乱,但是在哪里呢?而我该怎么做才能得到我想要的东西,也就是在脚本中获得与从命令行获得的解析相同的解析?

谢谢。

解决方法

read不解释引号,它只是将"one读为一个标记,而将two"读为另一个标记。 (请考虑一下如果外壳程序会评估随机位置的输入会导致出错的所有方式。Python2及其有缺陷的input()的教训也是一个很好的例证。)

如果您真的想评估事物,eval会这样做;但是它带来了一些警告,如果不小心的话,经常会导致安全问题。

取决于您要完成的工作,也许在单独的行中提供输入?或者,如果这些是用户提供的参数,则将其保留在"$@"中。还请注意,如何将它们的子集传递给函数,如果您想弄乱它,它将获得自己的本地"$@"

(可能会因不引述echo的参数而使自己感到困惑。请参阅When to wrap quotes around a shell variable。)

,

为什么不呢?

read将输入拆分为IFS中的每个 字符。使用未设置或默认的IFS,即空格,制表符或换行符。其他任何字符都不是特殊字符,引号也不是特殊字符。

很明显,我的报价水平很混乱,但是在哪里?

您错误地认为read足够聪明,可以解释引号。不是。此外,read会忽略\序列。阅读how to read a stream line by linebash manual word splitting

我该怎么做才能得到我想要的东西,即在脚本中获得与从命令行获得的解析相同的解析?

要获得与从命令行进行的相同分析,可以使用evaleval是邪恶的。 Eval command and security issues

echo \"one two\" three |
while IFS= read -r line; do
      eval "set $line"  # SUPER VERY UNSAFE DO NOT USE
      printf "%s\n" "$@"
done

使用eval时,恶意用户可能会echo '"$(rm -rf *)"' | ...立即删除您的文件。 Shell中最简单的解决方案是使用xargs,它(在大多数情况下会令人困惑)在解析输入时包括引号解析。

echo \"one two\" three | xargs -n1 echo

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...