【问题标题】:Single quotes inside a double-quoted string in bash not honoredbash中双引号字符串中的单引号不被尊重
【发布时间】:2016-10-17 18:19:31
【问题描述】:

我正在尝试在 bash 中分配一个变量:

assignssid="airport -I | awk '/ SSID/ {print substr($0, index($0, $2))}'"

当我当前执行此操作,然后运行echo "$assignssid" 时,结果类似于以下内容:

airport -I | awk '/ SSID/ {print substr(-bash, index(-bash, ))}'

如何让变量与引号内的代码一起使用?

【问题讨论】:

标签: bash shell variables terminal


【解决方案1】:

问题:双引号中的单引号不是句法

当您有"'$0'" 时,只有那些外引号是语法(并控制shell 如何扩展该值:内引号只是文字值,不要改变$0 的处理方式。


文字答案(仅限 bash):$''

如果您不想使用扩展,请不要使用双引号。

# assign the directory separately, just to make the line shorter for easier reading
dir=/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/

# now, expand the directory name in double quotes, but use the $'' quoting style otherwise
assignssid="$dir"$'airport -I | awk \'/ SSID/ {print substr($0, index($0, $2))}\''

$'' 内部,\' 是文字单引号(同样,\n 是换行符,\t 是制表符等),并且不会发生参数扩展($'$0''$0',不是"$0")。

执行此操作后,您可以看到 echoing 变量发出的命令带有完整的单引号内容:

$ echo "$assignssid"
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | awk '/ SSID/ {print substr($0, index($0, $2))}'

...或者,更贴近您可能预期的用例:

current_ssid=$(eval "$assignssid")

字面答案(POSIX sh):'"'"'

让我们以 不是 bash-only 的方式回答第一个问题:

dir=/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/
assignssid="$dir"'airport -I | awk '"'"'/ SSID/ {print substr($0, index($0, $2))}'"'"''

这个字符串的作用如下:

  • 第一个 ' 关闭单引号上下文
  • 第一个 " 打开一个双引号上下文
  • 以下' 是文字,因此成为您价值的一部分
  • 以下" 关闭双引号上下文
  • 最后的 ' 恢复原来的单引号上下文

最佳实践答案:使用函数存储代码

字符串变量根本不适合这项工作。相反,使用一个函数:

airport_dir=/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/
assignssid() {
    "$airport_dir"/airport -I | awk '/ SSID/ {print substr($0, index($0, $2))}'
}

...然后:

current_ssid=$(assignssid)

【讨论】:

    【解决方案2】:

    你可以“分而治之”。
    让我们将(非常)长的目录放在一个变量中:

    $ dir="/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources"
    

    让我们把 awk 命令放在第二个变量中:

    $ awkcmd='/ SSID/ {print substr($0, index($0, $2))}'
    

    由于文本在单引号内,$0$2 不会被 shell 扩展。

    然后,让我们加入你想要的变量:

    $ assignssid="$dir/airport -I | awk '$awkcmd'"
    

    在这种情况下,单引号起作用(出现在assignssid 变量中),因为它们在双引号内使用。

    而且,我假设您要执行的是:

    $ eval "$assignssid"
    

    以上内容适用于任何(合理的)shell。

    【讨论】:

    • nod -- 你可以做出比“任何合理的外壳”更强有力的声明——这取决于 POSIX sh 标准,所以即使是基线 POSIX shell没有实现像local 这样的无处不在的扩展就可以了。 +1。
    【解决方案3】:

    感谢大家的贡献。我想我找到了另一种方法 var=$(/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | awk '/SSID/ {print substr($0, index($0, $2))}')

    【讨论】:

    • ...所以您想运行 awk,并将输出存储在您的变量中?这个问题没有明确表达这个意图。 (这就是为什么解释您期望的输出是什么以及它与您获得的输出有何不同很重要的部分原因)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-09
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    相关资源
    最近更新 更多