i am trying to restrict users to give an unformatted message in git commit-message window. For that i created some formatted regex and trying to put that one in commit-msg hook.
But i am unable to compare the git commit-message string with below regex.

Could you please help me to resolve this ?

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"
        echo "Pre-Commit hook is failed. commit-message format not met regex    pattern Eg: TEST-123 #time 2w #comment added second line"
        exit 1
  • Welcome on StackExchange, I've edited your question to make it more readable. Take the time to read the tour to know a bit better how the site does work and how you could improve your question. Have a nice day. – Kiwy Jun 13 '18 at 7:16
  • If you have got any error running the script, please edit the question and include it in the question. – Rui F Ribeiro Jun 13 '18 at 7:22
  • What does the actual string look like? The one you're trying to match against that regex pattern – ilkkachu Jun 13 '18 at 7:24
  • Bash does not support Perl-like regular expressions. – Kusalananda Jun 13 '18 at 7:50
  • actual string would be like this: TEST-123 #time 2w #comment added second line – Sreenivas Reddy Jun 13 '18 at 8:03
  • (?:...) is a perl regexp operator. If you want to use those in a shell, you need zsh or ksh93. bash has no support for them. Anyway here, the standard ERE (...) could be used instead.
  • What \n matches is also unspecified in POSIX extended regexp which bash uses (on most systems, it will match on n only) but note that anyway . also matches on the newline character in EREs
  • anyway, regexps are not anchored in the [[ ... =~ ... ]] operator, so any <anything>* at the end would be redundant as it's sure to match as it matches at least the empty string.
  • what [A-Z] matches outside of the POSIX locale is pretty random in practice. It will likely match on the 26 uppercase letters of the English alphabet, but probably a lot more characters (even possibly sequences of characters)¹
  • Same for [0-9] which depending on the locale and the system matches on decimal digits and possibly more random characters.
  • unquoted parameter expansions has a very special meaning in shells, there's no reason you'd want to keep those $1/$regex... unquoted there.
  • When passing arbitrary arguments to commands, you need to make sure they are not treated as options. So file=$(cat -- "$1") or file=$(cat < "$1") or with ksh/zsh/bash: file=$(<"$1") (though it may fail to return a non-zero exit status upon failure).
  • echo can't be used for arbitrary data
  • it's a good idea to check for the success/failure of a command before carrying on to the next.
  • errors should generally go to stderr.

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
  echo >&2 invalid
  exit 1

A few extra notes:

  • command substitution $(cat < "$1") above strips all trailing newline characters. So would remove trailing empty lines from the content of the file.
  • bash contrary to zsh can't store the NUL character in its variables. If the input file contains some, they will be discarded (Which is probably just as well) with a warning message.


| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.