Escapando argumento no script bash?

3

Estou escrevendo um script em que quero verificar se um dos argumentos passados para ele é um grupo válido.

Eu tenho a linha

if [ 'grep -c -e '\b$2\b' /etc/group' -eq 0 ]; then
  echo "Error: $2 is not a valid group."
else

O que sempre me diz que os grupos válidos não são válidos.

Eu acho que é um problema de escape; Eu acho que é grepping para um grupo chamado $2 . A mensagem de erro mostra corretamente o argumento passado. No entanto, não tenho certeza se estou escapando de $2 dentro dos backticks corretamente.

Como faço para que esta linha funcione?

    
por user394 06.01.2012 / 16:01

3 respostas

7

A utilização da opção grep do -q é muito mais eficiente que a substituição de comandos.

if ! grep -q -e "^$2:" /etc/group; then
    echo "Error: $2 not a valid group" >&2
fi

O problema são aspas simples ( ' ) impedir a expansão da variável shell ( $ ). Você precisa usar aspas duplas ( " ).

    
por 06.01.2012 / 16:16
2
grep -q -e "^$2:" /etc/group

deve funcionar.

(aspas simples impedem a interpolação)

    
por 06.01.2012 / 16:16
1

Você está passando \b$2\b para grep literalmente por causa das aspas simples. Para permitir que $2 se expanda para o valor do argumento, use "$2" . Além disso, citar entre backquotes pode ser complicado; use $(…) , que tem o mesmo significado que '…' (substituição de comando), mas se comporta bem com relação a citações.

if [ $(grep -c -e "\b$2\b" /etc/group) -eq 0 ]; then …

Em seguida, contar as correspondências é muito complicado: você pode usar o status de retorno de grep para saber se houve correspondências. Passe a opção -q para informar a grep que você não está interessado em nenhuma saída, apenas no status de retorno.

if ! grep -q -e "\b$2\b" /etc/group; then …

Em seguida, sua pesquisa está errada. Você está procurando a palavra $2 , mas isso pode corresponder a um nome de usuário ou a uma parte de um nome de grupo que contenha um caractere de pontuação ou a mais algumas diferenças exóticas. O nome do grupo é o primeiro campo delimitado por dois pontos, então pesquise por isso.

if ! grep -q -e "^$2:" /etc/group; then …

Observe que você pode precisar limpar a entrada: $2 não deve conter nenhum caractere especial para grep ou que seja um delimitador de grupo.

case $2 in
  *[][\.*^$]*) echo "Unsupported character in the group name";;
esac
if ! grep -q -e "^$2:" /etc/group; then …

Por fim, grep /etc/group não é a ferramenta certa aqui, se você puder evitá-la. Você só pode encontrar nomes de grupos locais dessa maneira, não grupos vindos de NIS ou LDAP ou configurações incomuns. A maioria dos unices modernos (pelo menos Solaris, Linux e * BSD) tem um getent para recuperar entradas de bancos de dados do sistema, incluindo o banco de dados do grupo.

if ! getent group "$2" >/dev/null; then …

(para usuários, em vez de procurar em /etc/passwd , use getent passwd ou mais, de forma portável, chame id .)

    
por 07.01.2012 / 02:37