如何在 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 中转义单引号?的主要内容,如果未能解决你的问题,请参考以下文章