【问题标题】:sed: Can my pattern contain an "is not" character? How do I say "is not X"?sed:我的模式可以包含“不是”字符吗?我怎么说“不是X”?
【发布时间】:2011-11-23 03:46:38
【问题描述】:

sed 中的某个字符“不是”怎么说?

【问题讨论】:

  • [^X] 是除X 之外的任何字符。 PS 虽然我们知道你的意思,但 SED 不应该大写
  • @Sanjay 好的,我将取消大写 sed。下次能不能在回答区发个答案,不是cmets?

标签: regex sed


【解决方案1】:
[^x]

这是一个接受除x之外的任何字符的字符类。

【讨论】:

  • 我将添加来自 Mastering Regular Expressions 的警告。请注意,要与之匹配,那里必须有一些东西。正则表达式 'su[^x]' 将匹配 'sum' 和 'sun' 但不匹配 'su'。
  • 你如何修复它匹配你提到的'su'的情况?
  • @jcalfee314,我相信添加一个 ?像 'su[^x]?'意味着它应该匹配零个或其中一个字符。
  • 所以要拼出来,su[^x]\? 将匹配“sux”,因为子字符串“su”满足正则表达式。您将 x 从匹配中排除,而不是阻止带有 x 的内容匹配。 (如果条件之后有某些内容,这可能会起作用,例如su[^x]\?$
  • +1 用于按要求回答问题,但可能值得提供建议使用 alternation 来解决像 @jcalfee314 这样的人询问的常见实际案例,其中 "su[!x]" 还旨在匹配 "su" 后面没有任何字符:\(su[^x]\|su$\)(我认为更短的形式 su\([^x]\|$\) 也可以工作)。
【解决方案2】:

根据我自己的经验,下面的帖子支持这一点,sed 不支持使用“^”的正常正则表达式否定。我不认为 sed 有直接否定的方法......但如果你查看下面的帖子,你会看到一些解决方法。 Sed regex and substring negation

【讨论】:

  • 排序.. 这行得通: echo 'blahbloge.weg">yeah</a>' | sed 's@href="[^ http]@href="/@g'
  • 输出:blahbloge.weg">yeah</a>(仅匹配相对网址)
  • 这是不正确的。 sed 支持 [^...] 否定就好了。不过,也许您对这个结构的理解并不完整?不过,链接的问题很有用。
  • 但请注意,[^http] 会查找不是(换行符或)h、t 或 p 的单个字符。 (第二个 t 完全是多余的,但正则表达式引擎可以容忍。)
【解决方案3】:

对于那些对所选答案不满意,根据johnny's comment

'su[^x]' 将匹配 'sum' 和 'sun' 但不匹配 'su'。

您可以使用以下语法告诉 sed 到 not 匹配行与 x

sed '/x/! s/su//' file

See kkeller's answer for another example.

【讨论】:

  • 这也会跳过x su,即使它应该匹配。你可以做/sux/!s/su//,但这仍然会跳过su sux,可能是第一个,但不是第二个,su 应该匹配。理想情况下,OP 应该明确要求。
  • @tripleee 可靠的解决方案是\(su[^x]\|su$\)(我认为更短的形式su\([^x]\|$\) 也可以工作)。
【解决方案4】:

您的问题有两种可能的解释。就像其他人已经指出的那样,[^x] 匹配不是x 的单个字符。但是空字符串也不是x,所以也许你正在寻找[^x]\|^$

这些答案都没有扩展到多字符序列,这通常是人们正在寻找的。你可以煞费苦心地构建类似的东西

[^s]\|s\($\|[^t]\|t\($\|[^r]\)\)\)

编写一个不匹配str 的正则表达式,但sed 中更直接的解决方案是删除任何匹配 匹配str 的行,然后保留其余行;

sed '/str/d' file

Perl 5 引入了一个更丰富的正则表达式引擎,因此它是 Java、PHP、Python 等的标准引擎。因为 Perl 有助于支持 sed 语法的子集,您可以将一个简单的 sed 脚本转换为 Perl从这个扩展的正则表达式方言中使用一个有用的特性,例如否定断言:

perl -pe 's/(?:(?!str).)+/not/' file

将用not 替换不是str 的字符串。 (?:...) 是非捕获组(与许多sed 方言不同,非转义括号是Perl 中的元字符),(?!str) 是否定断言;为了使正则表达式匹配,字符串中此位置之后的文本不得为 str+ 重复此模式,直到匹配失败。请注意断言如何在匹配中的每个位置都为真,所以我们一次匹配一个字符与.(新手经常会犯这个错误,并且错误地只在例如较长模式的开头进行断言,但是这可能在某处匹配str,导致“泄漏”)。

【讨论】:

  • +1 在“删除 匹配 的每一行”sed 示例行之后,我还将包含一个“或对 匹配的每一行进行操作not match" 与一个简单的sed 示例说明如何做到这一点。 (就像我认为可行的sed '/str/! { ... },但如果我错了,那么总是有:bt 来构建任意条件分支。)
【解决方案5】:

除了所有提供的答案之外,您还可以在 sed 中使用符号 [^:[C_CLASS]:] 否定字符类,例如,[^[:blank:]] 将匹配不被视为空格字符的任何内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    • 2019-12-24
    • 2014-02-24
    • 2012-02-06
    相关资源
    最近更新 更多