无法在 shell 脚本中使用测试运算符将字符串与正则表达式进行比较

无法在 shell 脚本中使用测试运算符将字符串与正则表达式进行比较

我试图限制用户在 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 中使用它们,则需要zshksh93bash没有他们的支持。无论如何,这里(...)可以使用标准 ERE 。
  • \nPOSIX 扩展正则表达式中也未指定匹配的内容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ǴǶǷǸǺǼǾȀȂȄȆȈȊȌȎȐȒȘȚȜȞȦȨȪȬȮȰȲḀḂḄḆḈḊḌḎḐḒḔḖḘḚḜḞḠḢḤḦḨḪḬḮḰḲḴḶḸḺḼḾṀṂṄṆṈṊṌṎṐṒṔṖṘṚṜṞṠṢṤṦṨṪṬṮṰṲṴṶṸṺṼṾẀẂẄẆẈẊẌẎẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼẾỀỂỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪỬỮỰỲỴỶỸ

相关内容