【问题标题】:How to *not* expand "~" in tcsh backtick/eval wrapper?如何*不*在 tcsh 反引号/eval 包装器中扩展“~”?
【发布时间】:2016-03-01 02:11:35
【问题描述】:

我对“为什么 tcsh 是邪恶的”回答不感兴趣,这个问题需要 tcsh 才能使用。如果这是 tcsh 中的错误,请告诉我。

我通常很擅长引用输出,但我被一个我必须处理的用例难住了。这是简化的案例:

我有一个可以评估输出的可执行文件。有时它需要打印输出(到标准输出),所以我尝试使用 echo(内置)、/bin/echo 和 /bin/printf。

举个简单的例子,假设我的可执行文件名为“simpleWrap”,它输出

echo "hello world"

所以我运行(最终使用别名,但这无关紧要):

eval `simpleWrap`

正如预期的那样,我得到了:

hello world

但这就是问题所在。有时我需要在输出中添加波浪号。所以让我们尝试一些例子。我们将把波浪线放在 simpleWrap 输出中(这不是脚本的内容,而是它输出的内容):

echo "These are tildes:  ~ and \~ and \\~"

令人惊讶的是,当我现在评估 simpleWrap 的输出时,我得到:

These are tildes: /home/dave and \~ and \~

要么 ~ 扩展至我的主目录,要么 \ 保护它,但我无法摆脱反斜杠。

如何在带有反引号的 eval 的输出中打印一个“~”?

我相信反引号会迫使 ~ 扩展,但它们并没有以一致的方式进行。例如,如果我跳过反引号并执行以下操作:

eval echo "These are tildes:  ~ and \~ and \\~"

然后我得到一个一致的、预期的输出:

These are tildes: /home/dave and ~ and \~

反引号中的替换有什么问题,还是我错过了正确的引用可能性? (我也试过用单引号和双引号括起来无济于事)

【问题讨论】:

  • 我不明白你的例子或你想要做什么。 eval `simpleWrap` 不会产生“Hello world”;反引号产生“Hello world”,eval 尝试运行命令Hello world。话虽如此,一般来说,我更喜欢使用set noglob 来解决这个问题(然后稍后使用set glob 重新启用它)。
  • 请再读一遍解释 - simpleWrap outputs 'echo "hello world"',它不只是 echo hello world。
  • 为了避免这样的混淆,这就是为什么总是推荐Minimal, Complete, and Verifiable example ;-)
  • 虽然我在语言方面没有经验,但我只是投入了两分钱。也许尝试输出一个 unicode U+007E

标签: eval alias wrapper tcsh


【解决方案1】:

不同之处在于 shell 替换发生的顺序,以及解析 \ 的不同行为,当它位于双引号内时,而不是没有双引号。 p>

演示\的行为:

echo \~
=> ~
echo "\~"
=> \~
echo "\\~"
=> \~

场景 1

eval `simpleWrap`

这里,“simpleWrap”输出一个包含波浪线的“原始”字符串。然后将字符串原封不动地(没有替换)传递给 eval 命令(因为这就是反引号的工作方式),它基本上运行一个新的 shell。所以新的shell看到这个命令行:

echo "These are tildes:  ~ and \~ and \\~"

(请注意,eval 命令可以看到引号)。

这个命令的输出是你没想到的,即\~(表示A)和\\~(表示B)产生相同的输出。为什么?

首先,A 和 B 都没有被替换,因为只有当波浪号是单词中的第一个字符时才会发生波浪号替换,这两者都不是。

现在,对于 A,由于 \~ 不是已知的转义序列(例如,与 \n 不同),shell 保持原样,生成 \~

对于 B,\\一个已知的转义序列,因此 shell 正确地将其解释为 \,然后将其余字符串附加到它,再次生成 \~

场景 2

eval echo "These are tildes:  ~ and \~ and \\~"

这里,只有一个命令行,其中包括波浪线。首先,有 shell 替换,它既不影响 A 也不影响 B,但在这个阶段,引号会下降(它们用于将单词分组为单个参数,而不是传递给命令)。然后,eval 运行(echo 尚未运行),并将其作为输入传递:echo These are tildes: ~ and \~ and \\~

注意引号被丢弃。不带引号的命令的输出是您所期望的(参见上面的“演示”):

echo These are tildes:  /home/dave and \~ and \\~
=> These are tildes: /home/dave and ~ and \~

如何让它发挥作用?

去掉引号!

simpleWrap 应该打印这个:

echo These are tildes:  ~ and \~ and \\~

而不是这个:

echo "These are tildes:  ~ and \~ and \\~"

【讨论】:

  • 就是这样!感谢您的详尽解释-我没有想到要减少引用以解决问题。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-13
相关资源
最近更新 更多