Enquanto outros responderam sua pergunta específica, acrescentarei que
if [ -n "$(echo $1 | grep '^-[0-9][0-9]*$')" ]; then
É uma maneira incorreta de verificar se uma string corresponde a uma expressão regular por vários motivos:
- Você não pode usar
echo
para dados arbitrários
- Deixar uma expansão de parâmetro sem aspas como essa
$1
acima é o operador split + glob.
-
grep
não combina o regex com sua entrada completa, mas em cada linha de entrada. Então, ele retornaria verdadeiro em foo\n-0\nbar
, por exemplo.
- Um regexp pode corresponder ao comprimento zero, portanto, é errado, no caso geral, verificar se
grep
produz alguma saída (note que a substituição de comando remove caracteres de nova linha). É melhor usar grep -q
e confiar no status de saída de grep
, em vez de no [
, e também evitar a substituição de comando.
- Observe que o comando
grep
pode ser simplificado para grep -xE '-[0-9]+'
bash
, ksh93
e zsh
têm um operador dedicado para correspondência estendida de regexp. Para usá-lo de maneira portável e confiável em todos os três (e bash-3.1), a sintaxe é:
re='^-[0-9]+$'
if [[ $1 =~ $re ]]; then
echo matches
fi
yash
e zsh
também suportam:
if [ "$1" '=~' '^-[0-9]+$' ]; then
echo matches
fi
O comando padrão para fazer correspondência de regex de string (básica) é expr
:
if expr " $1" : ' -[0-9]\{1,\}$' > /dev/null; then
echo matches
fi
Observe que ^
(mas não $
) está implícito em expr
. Também usamos esse caractere de espaço principal para evitar problemas com valores de $1
que são expr
de operadores.
Observe também que, se a regex contiver \(...\)
, isso afetará o comportamento de expr
.
Em suma, é melhor usar awk
, que é outra maneira padrão / portátil de fazer isso (observe que awk
usa regexps estendidos):
if STRING=$1 RE='^-[0-9]+$' awk '
BEGIN{exit(ENVIRON["STRING"] !~ ENVIRON["RE"])}'; then
...
Ou use uma função:
re_match() {
STRING=$1 RE=$2 awk '
BEGIN{exit(ENVIRON["STRING"] !~ ENVIRON["RE"])}'
}
if re_match "$1" '^-[0-9]+$'
Nesse caso, você também pode alcançá-lo com uma construção padrão case
:
case $1 in
("" | *[!0-9-]* | [!-]* | - | ?*-*) ;;
(*) echo match;;
esac
Para usar grep
, você poderia usá-lo com a opção --null
(onde não há suporte como opção padrão) para que ele trabalhe em registros delimitados por NUL em vez de registros delimitados por nova linha. Como na maioria dos shells, $1
não pode conter NULs, isso deve ser seguro:
if printf %s "$1" | grep --null -xq '-[0-9]+$'; then
echo match
fi