Como se extrai o status de saída de um comando em uma variável?

14

Comecei a aprender Bash há alguns dias.

Estou tentando obter um status de saída da grepexpressão em uma variável como esta:

check=grep -ci 'text' file.sh

e a saída que eu recebi é

No command '-ic' found

Devo fazê-lo com um comando de pipe?

omri gilhar
fonte
6
Para o status de saída, você pode examinar $?logo após a conclusão do comando.
precisa saber
e você pode examinar a matriz PIPESTATUS se desejar o status de um dos comandos em um pipeline.
7286

Respostas:

26

Seu comando,

check=grep -ci 'text' file.sh

será interpretado pelo shell como "execute o comando -cicom os argumentos texte file.sh, e defina a variável checkcomo o valor grepem seu ambiente".


As lojas de shell o valor de saída de comando mais recentemente executado na variável ?. Você pode atribuir seu valor a uma de suas próprias variáveis ​​como esta:

grep -i 'PATTERN' file
check=$?

Se você deseja agir com base nesse valor, use sua checkvariável:

if [ "$check" -eq 0 ]; then
    # do things for success
else
    # do other things for failure
fi

ou você pode pular usando uma variável separada e ter que inspecionar $?todos juntos:

if grep -q -i 'pattern' file; then
  # do things (pattern was found)
else
  # do other things (pattern was not found)
fi

(observe -q, ele instrui grepa não produzir nada e a sair assim que algo corresponder; não estamos realmente interessados ​​no que corresponde aqui)

Ou, se você quiser "fazer as coisas" quando o padrão não for encontrado:

if ! grep -q -i 'pattern' file; then
  # do things (pattern was not found)
fi

$?Só é necessário salvar em outra variável se você precisar usá-la mais tarde, quando o valor em $?tiver sido substituído, como em

mkdir "$dir"
err=$?

if [ "$err" -ne 0 ] && [ ! -d "$dir" ]; then
    printf 'Error creating %s (error code %d)\n' "$dir" "$err" >&2
    exit "$err"
fi

No trecho de código acima, $?será substituído pelo resultado do [ "$err" -ne 0 ] && [ ! -d "$dir" ]teste. Salvá-lo aqui é realmente necessário apenas se precisarmos exibi-lo e usá-lo com exit.

Kusalananda
fonte
4

Sua pergunta não é clara, mas com base no código que você enviou, parece que você deseja que a variável checkarmazene o status de saída do grepcomando. A maneira de fazer isso é executar

grep -ci 'text' file.sh
check=$?

Ao executar um comando a partir de um shell, seu status de saída é disponibilizado através do parâmetro especial do shell $?,.

Isso está documentado pelo POSIX (o padrão para sistemas operacionais do tipo Unix) em sua especificação para o shell e a implementação do Bash está documentada em Parâmetros especiais .

Como você é um novato, eu recomendo fortemente que você comece com um bom livro e / ou tutorial on-line para entender o básico. Recomendações de recursos externos são desencorajadas nos sites Stack Exchange, mas eu sugiro o Bash Guide de Lhunath e GreyCat .

Anthony G - justiça para Monica
fonte
4

Você disse ao bash para definir a variável check=grepno ambiente que ela passa para o comando

-ci 'text' file.sh

mas cinão existe.

Acredito que você pretendia incluir esse comando entre back-ticks ou entre parênteses precedidos por um cifrão, qualquer um dos quais atribuiria a contagem de quantas linhas 'texto' foi encontrado (sem distinção entre maiúsculas e minúsculas) no arquivo:

check=`grep -ci 'text' file.sh`

check=$(grep -ci 'text' file.sh)

Agora $checkdeve ser 0 se não houver correspondências ou positivo se houver correspondências.

Monty Harder
fonte
1

Confuso por que usar -c ao verificar a saída? É usado para verificar quantas vezes algo corresponde - não se for bem sucedido ou não.

   -c, --count
          Suppress normal output; instead print a count of matching  lines
          for  each  input  file.  With the -v, --invert-match option (see
          below), count non-matching lines.  (-c is specified by POSIX.)

mas neste exemplo

check="$(grep --silent -i 'text' file.sh; echo $?)"

Ele não produz nada, exceto um código de saída, que é ecoado. Essa é a saída que a verificação de variável usa. Eu também prefiro porque é uma única linha.

Você pode substituir --silent por -q. Eu o uso, pois você não está interessado na saída grep, apenas se funcionou ou não.

   -q, --quiet, --silent
          Quiet;  do  not  write  anything  to  standard   output.    Exit
          immediately  with  zero status if any match is found, even if an
          error was detected.  Also see the -s  or  --no-messages  option.
          (-q is specified by POSIX.)

$ check=$(echo test | grep -qi test; echo $?) # check variable is now set
$ echo $check
0
$ check=$(echo null | grep -qi test; echo $?)
$ echo $check
1
Miati
fonte
1

A maneira correta de atribuir a saída do comando grep a uma variável é como @ monty-hard mencionado:

check=`grep -ci 'text' file.sh`
check=$(grep -ci 'text' file.sh)

No entanto, para atribuir o status de saída deste comando a uma variável, você deve usar o parâmetro shell $?logo após executar o comando, como mostrado abaixo:

grep -ci 'text' file.sh
check=$?
echo $check
Curioso
fonte