如何使用 bash 正则表达式、sed、grep 或 groovy 从 GitHub 压缩的提交消息中提取 Jira Id?

问题描述 投票:0回答:1

我想从压缩合并 GitHub PR 所产生的提交消息字符串中提取 Jira Id。如果存在多个 Jira Id,我想提取第一个。

如何使用 bash 正则表达式、sed、grep、groovy 或任何其他可用的命令行工具来完成此操作?

测试用例:

ABCD-1231 dummy title XYZ-566 (#423)
=> ABCD-1231

[ABCD-1232, XYZ-566] dummy title (#424)
=> ABCD-1232

[ABCD-1233] dummy title (#425)
=> ABCD-1233

ABCD-1234: dummy title (#426)
=> ABCD-1234

XYZ-567 dummy title (#427)
=> XYZ-567

(XYZ-568) dummy title (#428)
=> XYZ-568

"XYZ-569" dummy title (#429)
=> XYZ-569

dummy title XYZ-570 dummy title (#430)
=> XYZ-570

DUMMY title XYZ-571 dummy title (#431)
=> XYZ-571

'feature/XYZ-572' dummy title (#432)
=> XYZ-572

FEATURE|XYZ-573 dummy title (#433)
=> XYZ-573

<Feature\XYZ-574> dummy title (#434)
=> XYZ-574

dummy title FAKE-XYZ-575 dummy title (#435)
=> <nothing>

dummy title abcdXYZ-576 dummy title (#436)
=> <nothing>

Bash中,

"[^A-Z]*(([A-Z]+-[0-9]+)*.*) \(#([0-9]+)\)"
会失败

  • “功能|XYZ-573 虚拟标题 (#433)”
  • “[功能\XYZ-574]虚拟标题(#434)”
  • ...

并且 bash 似乎不支持如下所示的负向后查找:

".*[^A-Z]*((?<!([A-Z]+)-?)[A-Z]+-[0-9]+).*"

任何人都可以提出解决方案或完成此任务的正确工具吗?

regex bash groovy sed grep
1个回答
1
投票

您可以尝试使用 grep

-P
上启用
PCRE
引擎 选项。这可能取决于您的
grep
版本 服务器。它会让你使用环顾四周。

您还可以使用

-m 1
选项限制匹配行,但它 对我们没有多大帮助,因为提交消息在一行上。但是
-o
选项将仅o输出匹配项。然后我们可以将它传递给
head
,以便仅获取 grep 输出的第一行。

对于图案,我会用

(?<=^|[^\w-])[A-Z]+-\d+
尝试。 我使用了积极的lookbehind来匹配开头 该行或任何字符不是单词或连字符。

我在以下 bash 脚本中测试了您的所有提交消息:

#!/bin/bash

commits=(
    "ABCD-1231 dummy title XYZ-566 (#423)"
    "[ABCD-1232, XYZ-566] dummy title (#424)"
    "[ABCD-1233] dummy title (#425)"
    "ABCD-1234: dummy title (#426)"
    "XYZ-567 dummy title (#427)"
    "(XYZ-568) dummy title (#428)"
    '"XYZ-569" dummy title (#429)'
    "dummy title XYZ-570 dummy title (#430)"
    "DUMMY title XYZ-571 dummy title (#431)"
    "'feature/XYZ-572' dummy title (#432)"
    "FEATURE|XYZ-573 dummy title (#433)"
    "<Feature\XYZ-574> dummy title (#434)"
    "dummy title FAKE-XYZ-575 dummy title (#435)"
    "dummy title abcdXYZ-576 dummy title (#436)"
)

for (( i=0; i<${#commits[@]}; i++ ))
do
    echo ${commits[$i]}
    # A) My first attempt, using head to only get the first match.
    echo ${commits[$i]} | grep -P -m 1 -o '(?<=^|[^\w-])[A-Z]+-\d+' | head -n1

    # B) InSync's more sofisticated solution to match only the first
    # occurrence with the help of \K, which resets the starting point
    # of the reported match. This is a good way to consume characters
    # which we don't want in the output. It's also used because we can't
    # solve this with a positive lookbehind as the latter has to be a fixed
    # length pattern (not the case because of the ungreedy .*? pattern).
    # My positive lookbehind (?<=^|[^\w-]) can also be replaced by a
    # shorter negative lookbehind (?<![\w-])
    echo ${commits[$i]} | grep -P -m 1 -o '^.*?\K(?<![\w-])[A-Z]+-\d+'
done

编辑

谢谢@InSync,您的聪明解决方案不使用

head
和 通过使用 PCRE
\K
模式来重置起始点 报告比赛。它用来以一种不贪婪的方式消耗所有的 第一个 Jira Id 之前的字符。我已将其添加到批次中 上面 B) 点下。

输出,A) 和 B):

ABCD-1231 dummy title XYZ-566 (#423)
ABCD-1231
ABCD-1231
[ABCD-1232, XYZ-566] dummy title (#424)
ABCD-1232
ABCD-1232
[ABCD-1233] dummy title (#425)
ABCD-1233
ABCD-1233
ABCD-1234: dummy title (#426)
ABCD-1234
ABCD-1234
XYZ-567 dummy title (#427)
XYZ-567
XYZ-567
(XYZ-568) dummy title (#428)
XYZ-568
XYZ-568
"XYZ-569" dummy title (#429)
XYZ-569
XYZ-569
dummy title XYZ-570 dummy title (#430)
XYZ-570
XYZ-570
DUMMY title XYZ-571 dummy title (#431)
XYZ-571
XYZ-571
'feature/XYZ-572' dummy title (#432)
XYZ-572
XYZ-572
FEATURE|XYZ-573 dummy title (#433)
XYZ-573
XYZ-573
<Feature\XYZ-574> dummy title (#434)
XYZ-574
XYZ-574
dummy title FAKE-XYZ-575 dummy title (#435)
dummy title abcdXYZ-576 dummy title (#436)
© www.soinside.com 2019 - 2024. All rights reserved.