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

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

something ~* 'bla'

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

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

什么是正确的搜索?

【问题讨论】:

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

标签: linux bash escaping grep


【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-10
      • 2017-08-05
      相关资源
      最近更新 更多