【问题标题】:Minimal matching with sed与 sed 的最小匹配
【发布时间】:2016-10-24 03:49:23
【问题描述】:

我正在为 git 创建一个解析器,它允许包含 [ 的分支名称和同时包含 [] 的 cmets。所以,我需要在[的第一个实例之间拉取跟踪信息,然后是]就行了。

这是我尝试使用的:

sed -rn "s/^\*\ [^\[]*\[([^\]]*)\].*$/\1/p";

你们中的一些人会知道^\*\ 匹配是针对当前分支的。然后,我尝试匹配除[ 之外的所有内容,然后捕获]. 之前的所有内容。不幸的是,匹配似乎与我的第一个子句没有什么不同,即简单的.*\[(.*)\].*$. 任何包含成对方括号的提交都会使我的脚本变得疯狂。

我可以通过喂它来故意破坏我的条款:

* haha 2b35744 [twodeep: ahead 1] Bad comments contain hashes followed by brackets... bad2bad [].

请注意,sed 匹配在第二对方括号之间。我想匹配twodeep: ahead 1,但我的子句返回一个空字符串(匹配第二对方括号)。我觉得这可能是 awk 的情况。

【问题讨论】:

  • 不要将附加信息放入 cmets。编辑您的问题。此外,假设您的读者不知道 git 分支名称的样子。只需列出有效的输入和您期望的结果。您列出的输入是否碰巧在 git 中具有任何意义完全超出了您的问题的重点。
  • 请保持 cmets 文明和建设性
  • 早上好,乔恩。
  • 您似乎正在尝试解析 git branch -vvv 或类似的输出。你可能对 Git 的“管道”命令有更多的运气。如果是这样,您可能想查看或询问有关使用 Git 管道命令生成类似于 git branch 的输出的问题,但更适合您自己的目的(无论它们是什么)。同时,由于这是一个关于 sed 的问题,因此似乎应该删除 [git] 标记...
  • 这就是我正在做的事情,托雷克。我不熟悉 git 管道。这个标签似乎适合这个问题,虽然这是我在这个网站上问的第一个问题,所以我完全不熟悉它的操作。

标签: sed


【解决方案1】:

试试这个:

$ sed -rn 's/^\*[^[]*\[([^]]*).*/\1/p' <<< "* haha 2b35744 [twodeep: ahead 1] Bad comments contain hashes followed by brackets... bad2bad []."
twodeep: ahead 1

您不应该在字符范围内转义方括号,只需将它们放在列表的开头即可。所以你只需要在你的模式中用[^]][^\]]替换[^\]][^]]

【讨论】:

  • 贪婪匹配仍在捕获第二对括号之间的空字符串。哦,即使第二个括号之间有什么东西,我仍然想匹配第一对。
  • 除了您未能在捕获的字符串中分隔右方括号之外,这与我在问题中提供的匹配语句有何不同?
  • 不同的是,您不应像在[^\[][^\]]* 中那样在字符范围内转义[]。这就是为什么你的输出是空的。
  • 如果您不转义方括号,则正则表达式解析会将它们作为特殊字符捕获。你的“答案”肯定不是。
  • 你不能在字符列表中转义[],只需将它们放在列表的开头即可。见stackoverflow.com/a/11214820/1344961
【解决方案2】:

如果这还不是你所需要的:

$ sed 's/[^[]*.\([^]]*\).*/\1/' file
twodeep: ahead 1

然后编辑您的问题以提供更具代表性的示例输入/输出和更清晰的描述。

【讨论】:

  • 我今天将不得不对此进行更多研究。虽然我倾向于使用 sed 的 -r 选项,但您的匹配似乎有效。我正在使用这个表达式来匹配 git 存储库中活动分支的跟踪部分,由 'git branch -vv' 返回。
  • 不知道 git 的东西,但如果你能把它放在一边,只谈论进入和退出命令的文本,那么我很乐意提供帮助。不要使用-r 来启用带有 sed 的 ERE,顺便说一句,因为这是 GNU sed 特定的。请改用-E,它可以在 GNU sed 和其他变体中工作。在这种情况下,两者都不是必需的,因为您只需要 BRE。
【解决方案3】:

使用TXR

$ git 分支 -vvv | txr gitbranchvvv.txr - |头 在味精后面命名上游 MAKEFRESH 0 0 实现终结钩子。 alloca master 0 1195 检测 alloca。 awk-uwr-功能分支 0 0 WIP chk-manage-vec-branch 0 0 将 chk_manage_vec 用于静态插槽数组。 循环 0 0 WIP 卷曲 0 0 卷曲:在制品 调试器改进 1 0 WIP 删除索引分支主 8 882 WIP dict-branch master 0 1224 WIP

gitbranchvvv.txr中的代码:

@(collect)
@  (cases)
  @name @hash [@upstream: ahead @ah, behind @bh] @msg
@  (or)
  @name @hash [@upstream: ahead @ah] @msg
@  (or)
  @name @hash [@upstream: behind @bh] @msg
@  (or)
  @name @hash [@upstream] @msg
@  (or)
  @name @hash @msg
@  (bind upstream nil)
@  (end)
@  (maybe)
@    (bind (ah bh) (0 0))
@  (end)
@(end)
@(output)
NAME                           UPSTREAM            AHEAD   BEHIND MSG
@  (repeat)
@{name                      30} @{upstream  16} @{ah -8} @{bh -8} @msg
@  (end)
@(end)

可以压缩前面/后面的grokking。但这比复制和粘贴需要更多的努力;何必。此外,六个月后代码可能更难理解。

【讨论】:

    【解决方案4】:

    以下是适用于该应用程序的方法:

    git branch -vv | sed -rn 's/^\*\ (.*)$/\1/p' | awk -F\[ '{print $2}' | awk -F\] '{print $1}'
    

    这匹配活动分支,并解析第一个左方括号和下一个右方括号之间的位。分支名称允许包含右方括号。就其本身而言, sed 似乎匹配该行中字符的最后一个实例。使用 awk 会比单独使用 sed 更可靠。

    【讨论】:

    • 如果您使用的是 awk,则不需要 sed,您将使用 awk 肯定不会是这样的,并且到目前为止发布的解决方案完全符合您的要求因此,将这些内容放在一边并发布您自己的内容,这可能是您在示例输入/输出中没有展示的内容,这是非常粗鲁的。
    猜你喜欢
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    相关资源
    最近更新 更多