如何在 Bash/Grep 中转义单引号?

Posted

技术标签:

【中文标题】如何在 Bash/Grep 中转义单引号?【英文标题】:How to escape single quotes in Bash/Grep? 【发布时间】:2011-11-07 10:40:04 【问题描述】:

我想用 grep 搜索如下所示的字符串:

something ~* 'bla'

我试过了,但是 shell 删除了单引号 argh..

grep -i '"something ~* '[:alnum:]'"' /var/log/syslog

什么是正确的搜索?

【问题讨论】:

Shell 删除双引号内的单引号?我第一次看到它! :) 他在单引号内有双引号内有单引号:正则表达式以'"开头,而不仅仅是" @Matteo,是的,乍一看很难看 :) 【参考方案1】:

如果您确实需要在引号中查找引号中的引号,那么有一些丑陋的构造可以做到。

echo 'And I said, "he said WHAT?"'

按预期工作,但对于另一个级别的嵌套,以下不按预期工作

echo 'She said, "And I said, \'he said WHAT?\'"'

相反,您需要在单引号字符串外部转义内部单引号:

echo 'She said, "And I said, '\''he said WHAT?'\''"'

或者,如果您愿意:

echo 'She said, "And I said, '"'"'he said WHAT?'"'"'"'

它不漂亮,但它有效。 :)

当然,如果你把东西放在变量中,这一切都是没有意义的。

[ghoti@pc ~]$ i_said="he said WHAT?"
[ghoti@pc ~]$ she_said="And I said, '$i_said'"
[ghoti@pc ~]$ printf 'She said: "%s"\n' "$she_said"
She said: "And I said, 'he said WHAT?'"
[ghoti@pc ~]$ 

:-)

【讨论】:

感谢您的简要概述,我只是 +1 将您的分数提高到 10k :) @oldergod, \n 不受echo 的许多实现的支持。 bash 使用的内置 echo 支持它,但它在 Bourne 兼容模式下不起作用(即当 bash 以 /bin/sh 运行时),并且它不在 FreeBSD 的 tcsh 内置的 echo 中。如果您希望\n 始终如一地工作,我建议您使用printf。至于您的问题...我的建议是您进行实验...或更明智的建议是:如果代码不清楚,请使用不同的代码。 @mklement0,重新术语,是的,自从我写了那条评论以来,我已经更新了我的口语。 :) 重新转义序列,我知道你知道这是如何工作的,所以我认为我们一定是误传了。在 POSIX 模式下,bash 的内置 echo 不会将像 \n 这样的转义序列解释为两个字符 \ n。试试:bash --posix -c 'echo "one\ntwo"'。我还注意到,来自 coreutils 的 /bin/echo 的行为符合我的预期。另一方面,dash,IIRC 是 Ubuntu 上的默认 sh,在以 sh 启动时会解释转义序列。会不会是你用破折号测试的? @mklement0,实际上,这些序列的解释是针对XSI conformance,它(大部分)包括但不等同于 POSIX.1。正如您链接到的文档所述,“以下字符序列应在任何参数中在符合 XSI 的系统上被识别:” 我想知道会很好“POSIX 兼容模式”是否是指 POSIX.1、POSIX:2001 (SUS),我认为这将包括 XSI 或其他内容。 感谢您的深入挖掘,@ghoti;补充您的发现:具体来说,XSI 是符合 POSIX 要求的可选超集(仍然适用于当前的 POSIX 标准,POSIX.1-2008, 2013 edition)。 getconf _XOPEN_UNIX 告诉给定系统是否支持 XSI,getconf _XOPEN_VERSION 报告 XSI 版本。 OSX 10.11、Linux 3.x 内核系统均报告支持。 Linux 没有经过官方认证,但 OSX 是(UNIX 03),这就解释了为什么他们不遗余力地调整 Bash。【参考方案2】:
grep -i "something ~\* '[[:alnum:]]*'" /var/log/syslog

为我工作。

转义第一个 * 以匹配文字 * 而不是使其成为零个或多个匹配字符:~* 将匹配零个或多个出现的 ~~\* 匹配 ~* 之后的表达式 something:alnum: 周围使用双括号(参见示例here) 在[[:alnum::]] 之后使用* 不仅可以匹配单引号之间的一个 字符,还可以匹配其中的几个 单引号根本不需要转义,因为它们包含在受双引号限制的表达式中。

【讨论】:

【参考方案3】: 字符类用[[:alnum:]](两个括号)指定 [[:alnum:]] 仅匹配 一个 字符。匹配零个或多个字符[[:alnum:]]*

您可以使用" " 来引用正则表达式:

grep -i "something ~\* '[[:alnum:]]*'" /var/log/syslog

马特奥

【讨论】:

@Matteo - 如果要按字面意思理解的话,当然可以。 ~* 表示“零个或多个 '~' 字符”。 @Graham,感谢您的更正。我错过了他正在寻找文字“*”。【参考方案4】:

根据您的表达,您似乎首先使用',然后使用"。如果要转义单引号,可以使用 ' 并转义它们,或者使用双引号。此外,作为 Matteo cmets,字符类具有双方括号:

grep -i "something \~\* '[[:alnum:]]+'" /var/log/syslog

grep -i 'something ~* \'[[:alnum:]]+\'' /var/log/syslog

【讨论】:

以上是关于如何在 Bash/Grep 中转义单引号?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中转义单引号 ( ' )? [复制]

如何在 MySQL 中转义单引号

如何在 Sybase 中转义单引号

如何在单引号字符串中转义单引号

如何在 CSS 中转义单引号或双引号?

如何在jQuery变量中转义单引号