我通过TortoiseGit在Windows上使用Git,目前我正在尝试使用这个commit-msg钩子来检查提交消息行的长度。
当我只用ASCII字符编写消息时,一切都很好。但是当我用俄语写消息时,字符计数器产生的结果是实际长度的两倍。看起来计数器在将消息另存为 UTF-8 文件时使用默认的 Windows 编码或类似的东西。
一些亮点:
-
.git/COMMIT_EDITMSG
具有 UTF-8 编码; - 我的钩子中的
echo $line
正确显示非 ASCII 字符; -
${#line}
返回一个等于actual_length * 2
的值; - 我尝试了不同的方法来迭代一行中的字符,每次迭代器都将每个字节视为一个单独的字符。
更新 1:我想在不添加环境依赖项的情况下实现我的目标(即,无需安装 Python 等其他解释器(。
不要计算字节 — 计算字符数。 即,在您的编程语言中将(解码(输入从字节转换为字符。以 UTF-8 编码的俄语字符占用 2 个字节。示例(在 Python 中(:
$ python
>>> len('тест')
8
>>> len(u'тест')
4
>>> len('тест'.decode('utf-8'))
4
现在,echo $line | iconv --from-code UTF-8 --to-code cp866
做到了。
它涵盖了我的用例(消息中只需要西里尔文或基本拉丁字符(,但缺乏通用性。我希望有人知道一个更干净的解决方案。
这是我当前的脚本:
#!/bin/bash
#http://chris.beams.io/posts/git-commit/#seven-rules
cnt=0
while IFS='' read -r line || [[ -n "$line" ]]; do
cnt=$((cnt+1))
cp866_line=`echo $line | iconv --from-code UTF-8 --to-code cp866`
if [ $? -eq 0 ]; then
length=${#cp866_line}
else
length=${#line}
fi
if [ $cnt -eq 1 ]; then
# Checking if subject exceeds 50 characters
if [ $length -gt 50 ]; then
echo "Your subject line exceeds 50 characters"
exit 1
fi
i=$(($length-1))
last_char=${line:$i:1}
# Subject line must not end with a period
if [[ $last_char == "." ]]; then
echo "Your subject line ends with a period"
exit 1
fi
elif [ $cnt -eq 2 ]; then
# Subject must be followed by a blank line
if [ $length -ne 0 ]; then
echo "Your subject line is followed by a non-empty line"
exit 1
fi
else
# Any line in body must not exceed 72 characters
if [ $length -gt 72 ]; then
echo "The line "$line" exceeds 72 characters"
exit 1
fi
fi
done < "$1"