【问题标题】:Echo but retain all quotes回显但保留所有引号
【发布时间】:2019-11-03 18:56:23
【问题描述】:

是否可以回显文本并保留所有引号和双引号? 我想编写一个函数来复制当前写入终端的文本(完全带引号)。

由于我在 OSX 上,所以我必须使用 pbcopy:

pb(){echo "$@" | pbcopy}

但是pb osascript -e 'tell Application "iTerm" to display dialog "Job finished"' 确实返回了

osascript -e tell Application "iTerm" to display dialog "Job finished" 但不是

osascript -e tell 'Application "iTerm" to display dialog "Job finished"'.

【问题讨论】:

  • 从本质上讲,这是一个外壳转义问题。在 shell 中转义数据很痛苦,如果它同时有单引号和双引号,那就更痛苦了;这就是为什么我不会使用这样的 shell 函数。相反,要将小字符串写入 pbpaste,我会使用 pbcopy<<<"stdin to `pbcopy` is \"this\""。对于较长的文本,我会使用多行 heredoc pbcopy<<-'__eof__'。几个额外的字符非常值得清晰,它不需要函数初始化,所以也更“香草”。
  • 您好,感谢您的参与!我真的不知道如何使用这里的字符串。 (我可以在下面的答案中看到如何使用 heredocs)。只是pbcopy<<<"stdin to pbcopy`是\"this\""`不起作用

标签: macos function shell zsh


【解决方案1】:

pb 看到参数之前,shell 正在删除外部单引号。传递一个单个参数

pb "osascript -e 'tell Application \"iTerm\" to display dialog \"Job finished\"'"

pb,并将其定义为

pb () {
    printf '%s\n' "$1" | pbcopy
}

不过,使用 here 文档可能同样容易,而不是定义一个将其参数提供给 pbcopy 的函数:

$ pbcopy <<'EOF'
osascript -e 'tell Application "iTerm" to display dialog "Job finished"'
EOF

打字稍微多一点,但不需要嵌套这么多引号。

【讨论】:

  • 有效。只需准备好引用并将输入转义到pb
  • 感谢您的评论。我真的希望有一种更好的方法,而无需转义引号。现在真的有其他选择吗?我认为 bash 会比这更强大。
  • @Tillus 你必须意识到像pb osascript -e 'tell Application ...'这样的命令是用shell语言编写的,它的在那种语言中的含义是运行pb命令,带有参数“osascript”、“-e”和“tell Application ...”。最后一个参数周围的单引号是 not 参数的一部分,它们只是删除其中字符的正常特殊效果(例如,空格作为参数分隔符)。这是它们在shell语法中的含义。您要求的是您的pb 命令不符合shell 语法
  • 感谢 Gordon,此评论帮助我找到了解决方案(目前在其他答案 cmets 中描述)
【解决方案2】:

是否可以回显文本并保留所有引号和双引号?我想写一个函数来复制当前写入终端的文本(完全带引号)。

让我们来探讨一下“当前写入终端”是什么意思。如果我理解正确,您希望在调用时向 shell 命令提供任意输入。换句话说,您有一些文本要添加到复制缓冲区中,并且您希望将其发送到pbcopy 的标准输入以执行此操作。

作为这个特定问题的解决方案,shell 函数不合适。这是因为需要使用受 shell 解释的参数调用 shell 函数,因此在调用 pb 和定义它时都必须小心地转义它们。这些字符串可以转义。但这很不方便,一方面是因为有几个特殊字符需要在双引号字符串中转义,但' 本身不能在单引号字符串中转义。

让我们探索一些其他选项。

$ pbcopy <<< "this is a simple one-line string directly from the command line.  Since it's an argument to pbcopy it needs to be escaped."
$ pbpaste
this is a simple one-line string directly from the command line.  Since it's an argument to pbcopy it needs to be escaped.

这里我们告诉shell 将文本提供给pbpaste 的标准输入。我们仍然需要对字符串进行转义。但我们不必将它传递到任何地方或再次正确引用它以使其成为有效的 shell 参数。

或者我们可以向pbcopy 提供多行字符串数据,而不必使用这种特殊的 here-doc 语法对其进行引用:

$ pbcopy <<-'-my-chosen-delimiter'
> Since this string's delimiter is single quoted,
> no interpolation will occur.  That means " double quotes
> have no meaning, nor does ' single quotes, $dollar signs
> or other such meaningful bash syntaxes.
> -my-chosen-delimiter

$ pbpaste
Since this string's delimiter is single quoted,
no interpolation will occur.  That means " double quotes
have no meaning, nor does ' single quotes, $dollar signs
or other such meaningful bash syntaxes.

我认为 bash 会比这更强大。

嗯,一方面,我认为这是一个很好的机会来比较和对比命令行参数(它们在设计上是固有的位置,因此必须解析和分割,通常是参数之间的空格)输入和输出用| 管道表示的流。 I/O 流旨在保存任意数据;您想将一个放入 shell 解析的变量列表不是 bash 的错。您在这里观察到的不是 bash 的强大功能,而是您的 bash 知识的功能限制。

但另一方面,你是对的。对用户交互式命令行界面的让步、实现向后兼容性的大量历史限制以及许多有效的设计考虑因素使bash 成为现实。我发现它及其同类是迄今为止最强大的计算机用户界面。但我不会用它来组装复杂的应用程序,因为坦率地说,它在语法上很困难。所以不要指望 bash 不是。如果你不想理解它的古怪和深奥的不规则性,坚持使用一些更新和更迂腐的东西,比如 python、go、ruby、node 或任何非以 unix 为中心的人现在运行的东西:P

【讨论】:

  • 感谢您的精彩帖子,感谢您向我展示了 bash 的极限。最后,我为我的个人脚本找到了一个解决方案,我将在一个新的答案中介绍它。它确实帮助我将命令视为参数的结合而不是纯文本。
  • 不幸的是,由于某种原因我无法发布答案...所以禁止我大声笑。所以我在这里发布我的答案。我会在以后允许的时候添加它..
  • ``` #!/bin/sh for var in "$@" do if [ $(wc -w 1 ] then all="${all} '${var}'" else all="${all} ${var}" fi;完成回声$all | pbcopy ``` 这个脚本解决了我的问题。它遍历脚本“$@”的所有参数,然后我简单地计算每个参数的字数。如果单词的数量低于 2,则不需要额外的引号,否则会在参数周围添加引号(在读取包含多个单词的参数时这些引号会丢失)。
  • POSIX [ 没有定义 &gt; 运算符;不能保证会起作用。如果您有一个特定的 shell,确实 定义了 &gt; 运算符,那么请使用该 shell,而不是 /bin/sh。不过,您可能需要-gt,因为您需要进行数值比较。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
  • 1970-01-01
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
  • 2011-03-19
  • 1970-01-01
相关资源
最近更新 更多