【问题标题】:foo[E1,E2,...]* glob matches desired contents, but foo[E1,E2,...]_* does not?foo[E1,E2,...]* glob 匹配所需的内容,但 foo[E1,E2,...]_* 不匹配?
【发布时间】:2015-07-30 03:52:08
【问题描述】:

我今天在 globbing 时看到 Bash Shell 的行为有些奇怪。

所以我使用以下 Glob 运行 ls 命令:

ls GM12878_Hs_InSitu_MboI_r[E1,E2,F,G1,G2,H]* | grep ":"

结果符合预期

GM12878_Hs_InSitu_MboI_rE1_TagDirectory:
GM12878_Hs_InSitu_MboI_rE2_TagDirectory:
GM12878_Hs_InSitu_MboI_rF_TagDirectory:
GM12878_Hs_InSitu_MboI_rG1_TagDirectory:
GM12878_Hs_InSitu_MboI_rG2_TagDirectory:
GM12878_Hs_InSitu_MboI_rH_TagDirectory:

但是,当我通过引入下划线来更改相同的正则表达式时

ls GM12878_Hs_InSitu_MboI_r[E1,E2,F,G1,G2,H]_* | grep ":"

我的预期结果是如上所示的完整集,但我得到的是一个子集:

GM12878_Hs_InSitu_MboI_rF_TagDirectory:
GM12878_Hs_InSitu_MboI_rH_TagDirectory:

当我在星号前引入下划线符号时,有人可以解释我的逻辑有什么问题吗?

我正在使用 Bash。

【问题讨论】:

  • 顺便说一句——ls | grep 是一种不应该在生产代码中使用的反模式。见mywiki.wooledge.org/ParsingLs
  • 谢谢!这个页面信息量很大!

标签: regex linux bash shell glob


【解决方案1】:

你误解了你的 glob 在做什么。

你期待这个:

GM12878_Hs_InSitu_MboI_r[E1,E2,F,G1,G2,H]*

成为一个包含任何逗号分隔段的文件,但这不是[] globbing 所做的。 [] globbing 是一个字符类扩展。

比较:

$ echo GM12878_Hs_InSitu_MboI_r[E1,E2,F,G1,G2,H]
GM12878_Hs_InSitu_MboI_r[E1,E2,F,G1,G2,H]

到你想要得到的东西(这是大括号{} 扩展):

$ echo GM12878_Hs_InSitu_MboI_r{E1,E2,F,G1,G2,H}
GM12878_Hs_InSitu_MboI_rE1 GM12878_Hs_InSitu_MboI_rE2 GM12878_Hs_InSitu_MboI_rF GM12878_Hs_InSitu_MboI_rG1 GM12878_Hs_InSitu_MboI_rG2 GM12878_Hs_InSitu_MboI_rH

你想要后一种扩展。

你的扩展使用了一个匹配字符E-H1-2,字符类;它等同于:

GM12878_Hs_InSitu_MboI_r[EFGH12,]_*

正如我希望您现在看到的那样,它不会匹配任何两个字符条目(没有下划线的版本会匹配)。

【讨论】:

    【解决方案2】:

    文件系统全局中的* 不像正则表达式中的*。在正则表达式中,* 表示“0 或多个前面的模式”,但在文件系统 glob 中,它表示“任何大小的任何东西”。因此,在您的第一个示例中,_ 只是来自* 的“任何东西”的一部分,但在第二个示例中,您将匹配字符类中的任何单个字符(而不是您似乎试图定义的模式)后面是_,后面是任何东西。

    此外,字符类的工作方式与您尝试使用它们的方式不同。 [...] 将匹配括号内的任何字符,因此您的模式实际上与 [EFGH12,] 相同,因为这些都是您定义的类中的所有字母。

    要获得你想要的模式分组,你应该使用{ 而不是[ like

    ls GM12878_Hs_InSitu_MboI_r{E1,E2,F,G1,G2,H}_* | grep ":"
    

    【讨论】:

      【解决方案3】:

      据我所知,并且this article 支持我,方括号不能作为一种选择,而是作为一个字符集,所以使用[E1,E2,F,G1,G2,H] 实际上等于恰好出现一次[EGHF12,]。然后,您可以将第二个结果解释为“EGHF12, 的一个字符和一个下划线”,它匹配 GM12878_Hs_InSitu_MboI_rF_TagDirectory: 但不匹配 GM12878_Hs_InSitu_MboI_rG1_TagDirectory:(有 r 后跟更多“一次出现...”) .

      第一个正则表达式有效,因为您使用了星号,它与错误的[...] 匹配。

      正确的表达方式是:

      ls GM12878_Hs_InSitu_MboI_r{E1|E2|F|G1|G2|H}* | grep ":"
      

      【讨论】:

      • 对问题的正确解释,但这不是他想要的正确外壳扩展。 Shell glob 不是正则表达式。
      • 我知道正则表达式不是 shell glob,你能解释一下我的回答有什么问题吗?
      • 运行echo GM12878_Hs_InSitu_MboI_r{E1|E2|F|G1|G2|H}。你得到/看到了什么?
      猜你喜欢
      • 2020-01-03
      • 2012-12-22
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      相关资源
      最近更新 更多