我试图限制用户在 git commit-message 窗口中给出未格式化的消息。为此,我创建了一些格式化的正则表达式,并尝试将其放入 commit-msg 挂钩中。
但我无法将 git commit-message 字符串与下面的正则表达式进行比较。
你能帮我解决这个问题吗?
regex="[A-Z]{3,}-[0-9][0-9]* #time (?:[0-9]+[wdhm])+ #comment (.|\n)*"
file=`cat $1`
echo $regex
echo $file
if [[ "$file" =~ $regex ]]; then
echo "Valid date"
else
echo "Pre-Commit hook is failed. commit-message format not met regex pattern Eg: TEST-123 #time 2w #comment added second line"
exit 1
fi
答案1
(?:...)
是一个 Perl 正则表达式运算符。如果您想在 shell 中使用它们,则需要zsh
或ksh93
。bash
没有他们的支持。无论如何,这里(...)
可以使用标准 ERE 。\n
POSIX 扩展正则表达式中也未指定匹配的内容bash
(在大多数系统上,它仅匹配n
),但请注意,无论如何.
也匹配 ERE 中的换行符- 无论如何,正则表达式没有锚定在
[[ ... =~ ... ]]
运算符中,因此<anything>*
末尾的任何内容都是多余的,因为它肯定会匹配,因为它至少匹配空字符串。 [A-Z]
在实践中,POSIX 语言环境之外的匹配内容是相当随机的。它可能会匹配英文字母表中的 26 个大写字母,但可能会匹配更多字符(甚至可能是字符序列)- 相同,
[0-9]
具体取决于区域设置和系统匹配十进制数字和可能更多的随机字符。 - 不带引号的参数扩展在 shell 中具有非常特殊的含义,您没有理由将这些
$1
/$regex...
不带引号保留在那里。 - 将任意参数传递给命令时,您需要确保它们不被视为选项。所以
file=$(cat -- "$1")
或file=$(cat < "$1")
或与 ksh/zsh/bash:(file=$(<"$1")
尽管失败时可能无法返回非零退出状态)。 echo
不能用于任意数据- 在执行下一个命令之前检查命令是否成功/失败是个好主意。
- 错误通常应该发送到 stderr。
uppercase=ABCDEFGHIJKLMNOPQRSTUVWXYZ
digit=0123456789
regexp="^[$uppercase]{3,}-[$digit]+ #time ([$digit]+[wdhm])+ #comment "
file=$(cat < "$1") || exit
printf '%s\n' "regexp: $regexp" "file: $file"
if [[ "$file" =~ $regexp ]]; then
echo valid
else
echo >&2 invalid
exit 1
fi
一些额外的注意事项:
$(cat < "$1")
条带上方的命令替换全部尾随换行符。因此将从文件内容中删除尾随空行。bash
相反,zsh
不能将 NUL 字符存储在其变量中。如果输入文件包含一些,它们将被丢弃(这可能也是如此)并带有警告消息。
¹ On my GNU system, in a en_GB.UTF-8
locale (typical in Britain), it matches on at least ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝĀĂĄĆĈĊČĎĐĒĔĖĘĚĜĞĠĢĤĦĨĪĬĮİIJĴĶĹĻĽĿŁŃŅŇŊŌŎŐŒŔŖŘŚŜŞŠŢŤŦŨŪŬŮŰŲŴŶŸƁƆƇƊƎƏƐƓƘƟƠƢƯƳDŽDžLJLjNJNjǍǏǑǓǕǗǙǛǞǠǢǤǦǨǪǬDZDzǴǶǷǸǺǼǾȀȂȄȆȈȊȌȎȐȒȘȚȜȞȦȨȪȬȮȰȲḀḂḄḆḈḊḌḎḐḒḔḖḘḚḜḞḠḢḤḦḨḪḬḮḰḲḴḶḸḺḼḾṀṂṄṆṈṊṌṎṐṒṔṖṘṚṜṞṠṢṤṦṨṪṬṮṰṲṴṶṸṺṼṾẀẂẄẆẈẊẌẎẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼẾỀỂỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪỬỮỰỲỴỶỸ