Esta é a primeira vez que faço scripts bash, então provavelmente estou cometendo um erro fácil.
Basicamente, estou tentando escrever um script que obtenha os grupos de um usuário e, se eles estiverem em um determinado grupo, ele registrará isso de acordo. Evidentemente, haverá mais funcionalidades, mas não faz sentido construir isso quando não consigo nem fazer o regex funcionar!
Até agora, eu tenho isso:
#!/bin/bash
regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
# example output
groups="username : username usergroup"
echo "$groups" >> /home/jrdn/log
if [[ "$groups" =~ $regex ]]; then
echo "Match!" >> /home/jrdn/log
else
echo "No match" >> /home/jrdn/log
fi
Em todos os lugares em que experimentei esse regex, ele funciona. Mas no script bash, ele só gera o $groups
, seguido por No match
. Então, alguém pode me dizer o que há de errado com isso?
Responder1
De man 7 regex
:
Uma expressão entre colchetes é uma lista de caracteres entre "[]". …
… Para incluir um '-' literal, torne-o o primeiro ou o último caractere…. [Todos] outros caracteres especiais, incluindo '\', perdem seu significado especial dentro de uma expressão entre colchetes.
Tentar o regexp com egrep gera um erro:
$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end
Aqui está uma versão mais simples, que também dá um erro:
$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end
Como \
não é especial, é um intervalo, exatamente como [a-z]
seria. Você precisa colocar o seu -
no final, como [_-]
ou:
echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup
Isso deve funcionar independentemente da sua versão da libc (em egrep ou bash).
editar:Na verdade, isso também depende das configurações de localidade. A página de manual avisa sobre isso:
Os intervalos dependem muito da sequência de agrupamento e os programas portáteis devem evitar depender deles.
Por exemplo:
$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'
\_
Claro, mesmo que não tenha dado erro, não está fazendo o que você deseja:
$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'
\^_
É um intervalo que em ASCII inclui \
, [
, ^
, e _
.
Responder2
Regra geral com regexps (e quaisquer bugs em trechos maiores de código): corte-o e reconstrua-o passo a passo ou use a divisão ao meio - o que funcionar melhor para você.
Nesse caso, o culpado acabou sendo o sublinhado - escapar dele com uma barra invertida fez com que funcionasse.