Não é possível comparar string com regex usando o operador de teste no shell script

0

Estou tentando restringir os usuários a fornecer uma mensagem não formatada na janela git commit-message. Para isso eu criei algum regex formatado e tentei colocar aquele no hook-commit msg. Mas não consigo comparar a string git commit-message com abaixo de regex.

Você poderia me ajudar a resolver isso?

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
    
por Sreenivas Reddy 13.06.2018 / 09:09

1 resposta

2

  • (?:...) é um operador perl regexp. Se você quiser usá-los em um shell, precisará de zsh ou ksh93 . bash não tem suporte para eles. De qualquer forma aqui, o padrão ERE (...) poderia ser usado no lugar.
  • O que \n corresponde também não é especificado na regexp estendida POSIX que bash usa (na maioria dos sistemas, corresponderá a n apenas), mas observe que de qualquer forma . também corresponde ao caractere de nova linha em EREs
  • de qualquer forma, os regexps não são ancorados no operador [[ ... =~ ... ]] , portanto, qualquer <anything>* no final seria redundante, já que certamente corresponderá, pois corresponderá pelo menos à string vazia.
  • o que [A-Z] corresponde fora do código do POSIX é bastante aleatório na prática. Ele provavelmente corresponderá às 26 letras maiúsculas do alfabeto inglês, mas provavelmente muito mais caracteres (até mesmo possíveis sequências de caracteres) ¹
  • O mesmo que [0-9] , dependendo da localidade e do sistema, corresponde a dígitos decimais e possivelmente a mais caracteres aleatórios.
  • expansões de parâmetros sem aspas tem um significado muito especial em shells, não há motivo para você querer manter esses $1 / $regex... sem aspas lá.
  • Ao passar argumentos arbitrários para comandos, você precisa garantir que eles não sejam tratados como opções. Portanto, file=$(cat -- "$1") ou file=$(cat < "$1") ou com ksh / zsh / bash: file=$(<"$1") (embora possa falhar ao retornar um status de saída diferente de zero em caso de falha).
  • echo não pode ser usado para dados arbitrários
  • é uma boa ideia verificar o sucesso / fracasso de um comando antes de prosseguir para o próximo.
  • os erros geralmente devem ir para 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

Algumas notas extras:

  • substituição de comando $(cat < "$1") acima de strips todos caracteres de nova linha à direita. Assim, removeríamos linhas vazias finais do conteúdo do arquivo.
  • bash ao contrário de zsh não pode armazenar o caractere NUL em suas variáveis. Se o arquivo de entrada contiver alguns, eles serão descartados (o que provavelmente é bom também) com uma mensagem de aviso.

¹ No meu sistema GNU, em um en_GB.UTF-8 locale (típico da Grã-Bretanha), ele corresponde em pelo menos ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÉÊËËÎÍÎÑÒÓÔÕÖØÙÚÛÜÝÄĂĈĊČĎĐĒĔĖĘĚĜĞĠĢĤĦĨĪĬĮİIJĴĶĹĻĽĿŁŃŅŇŊŌŎŐŒŔŖŘŚŜŞŠŢŤŦŨŪŬŮŰŲŴŶŸƁƆƇƊƎƏƐƓƘƟƠƢƯƳDŽDžLJLjNJNjǍǏǑǓǕǗǙǛǞǠǢǤǦǨǪǬDZDzǴǶǷǸǺǼǾȀȂȄȆȈȊȌȎȐȒȘȚȜȞȦȨȪȬȮȰȲḀḂḄḆḈḊḌḎḐḒḔḖḘḚḜḞḠḢḤḦḨḪḬḮḰḲḴḶḸḺḼḾṀṂṄṆṈṊṌṎṐṒṔṖṘṚṜṞṠṢṤṦṨṪṬṮṰṲṴṶṸṺṼṾẀẂẄẆẈẊẌẎẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼẾỀỂỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪỬỮỰỲỴỶỸ

    
por 13.06.2018 / 10:33