【问题标题】:Bash lookahead regex for git commit messages does not work "^[A-Z](?!.*ed).*$"git 提交消息的 Bash 前瞻正则表达式不起作用 "^[A-Z](?!.*ed).*$"
【发布时间】:2020-09-23 03:01:30
【问题描述】:

我正在尝试为 git 提交消息强制执行某种消息格式。 正则表达式应强制消息以大写字符开头,并且第一个单词是命令式。

我目前正在使用这个正则表达式:^[A-Z]\(?!.*ed\).*$

有效:

  • 添加新文件
  • 更新角色模型

无效:

  • 添加了新文件
  • 添加新文件
  • 添加了新文件
  • 更新的角色模型
  • 更新角色模型

虽然所有只有正则表达式的工具似乎都接受这个正则表达式,但 bash 不接受。 ed 排除部分似乎是问题所在:(?!.*ed)

bash 正则表达式不支持负向预测吗?

这是我的 bash 脚本:

msg="Add new file"

if [[ $msg =~ ^[A-Z](?!.*ed).*$ ]]; then
    echo "Correct"
else
    echo "Wrong"
fi

谢谢!

【问题讨论】:

标签: regex bash git


【解决方案1】:

BASH 正则表达式不支持前瞻断言。

但是,这里不需要使用任何前瞻。您可以使用 BASH glob 匹配来做到这一点:

[[ $msg = [A-Z]* && $msg != *ed* ]]

【讨论】:

  • 感谢这将适用于具体的例子。但它也会过滤任何在我猜想的文本中任何地方包含“ed”字符的东西。不过,我应该为这种情况提供一个示例-我的错。它还需要接受以下字符串:“为延迟调试日志添加新文件”
  • 你可以匹配任何类似 [[ $msg = *'Add new file for delayed debug logging' * ]].
【解决方案2】:

使用grep -P,它使用 Perl 正则表达式:

for msg in 'Add new file' 'add new file' 'Added new file' ; do
    if [[ $( grep -Pc '^[A-Z](?!.*ed).*$' <<< ${msg} ) != 0 ]]; then
        echo "Correct: ${msg}"
    else
        echo "Wrong: ${msg}"
    fi
done

输出:

Correct: Add new file
Wrong: add new file
Wrong: Added new file

这里,grep 使用以下选项:
-P:使用 Perl 正则表达式。
-c:打印匹配行数。

另请参阅:
grep manual

【讨论】:

  • 原来我的正则表达式并不完全符合我的意图,因为我想确保只有第一个单词没有使用过去时。但是使用这种方法很容易将其更改为: ^[A-Z](?!\w*ed).*$ 这也将正确地允许类似的东西(请原谅无意义的消息内容):'添加新文件以延迟调试日志记录'。有了这个改变,它就可以工作了。谢谢!
猜你喜欢
  • 2015-06-30
  • 2011-07-21
  • 1970-01-01
  • 2017-04-22
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多