Jak wyodrębnić status wyjścia polecenia do zmiennej?

14

Zacząłem uczyć się języka Bash kilka dni temu.

Próbuję uzyskać status wyjścia grepwyrażenia w zmiennej takiej jak ta:

check=grep -ci 'text' file.sh

a wyjście, które mam, to

No command '-ic' found

Czy powinienem to zrobić za pomocą polecenia potoku?

omri gilhar
źródło
6
Aby sprawdzić status wyjścia, możesz sprawdzić $?zaraz po zakończeniu komendy.
coffeMug
i możesz sprawdzić tablicę PIPESTATUS, jeśli chcesz mieć status jednego z poleceń w potoku.
cas

Odpowiedzi:

26

Twoje rozkaz

check=grep -ci 'text' file.sh

będą interpretowane przez powłokę jako „uruchom polecenie -ciz argumentami texti file.shi ustaw zmienną checkna wartość grepw jej środowisku”.


Powłoka przechowuje w zmiennej wartość wyjściową ostatnio wykonanego polecenia ?. Możesz przypisać jego wartość do jednej ze swoich zmiennych, takich jak to:

grep -i 'PATTERN' file
check=$?

Jeśli chcesz zastosować tę wartość, możesz albo użyć swojej checkzmiennej:

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

lub możesz pominąć użycie oddzielnej zmiennej i konieczność sprawdzenia $?wszystkich razem:

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

(zwróć uwagę -q, że instruuje, grepaby niczego nie wysyłać i wychodzić, gdy tylko coś się dopasuje; tak naprawdę nie jesteśmy zainteresowani tym, co pasuje tutaj)

Lub, jeśli chcesz po prostu „robić rzeczy”, gdy wzór nie zostanie znaleziony:

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

Zapisywanie $?w innej zmiennej jest zawsze potrzebne tylko wtedy, gdy trzeba jej użyć później, gdy wartość w $?została zastąpiona, jak w

mkdir "$dir"
err=$?

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

W powyższym fragmencie kodu $?zostanie zastąpiony wynikiem [ "$err" -ne 0 ] && [ ! -d "$dir" ]testu. Zapisanie go tutaj jest naprawdę konieczne tylko wtedy, gdy musimy go wyświetlić i używać z exit.

Kusalananda
źródło
4

Twoje pytanie jest niejasne, ale w oparciu o przesłany kod wygląda na to, że chcesz, aby zmienna checkprzechowywała status wyjścia greppolecenia. Sposobem na to jest uruchomienie

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

Podczas uruchamiania polecenia z powłoki, jej status wyjścia jest udostępniane za pośrednictwem specjalnego parametru powłoki $?.

Jest to udokumentowane przez POSIX (standard dla systemów operacyjnych typu Unix) w specyfikacji dla powłoki, a implementacja Bash jest udokumentowana w parametrach specjalnych .

Ponieważ jesteś nowym uczniem, zdecydowanie polecam zacząć od dobrej książki i / lub samouczka online, aby uzyskać podstawy. Zalecenia dotyczące zasobów zewnętrznych są odradzane na stronach Stack Exchange, ale sugerowałbym Bash Guide Lhunatha i GreyCata .

Anthony Geoghegan
źródło
4

Poleciłeś bashowi ustawić zmienną check=grepw środowisku, które przekazuje do polecenia

-ci 'text' file.sh

ale cinie istnieje.

Sądzę, że chciałeś zawrzeć to polecenie w tyknięciach wstecz lub w nawiasach poprzedzonych znakiem dolara, z których każdy przypisałby liczbę wierszy, w których „tekst” został znaleziony (bez rozróżniania wielkości liter) w pliku:

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

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

Teraz $checkpowinno być 0, jeśli nie ma żadnych dopasowań, lub dodatnie, jeśli były jakieś dopasowania.

Monty Harder
źródło
1

Mylić, dlaczego przy użyciu -c podczas sprawdzania danych wyjściowych? Służy do sprawdzania, ile razy coś jest dopasowywane - nie, czy się powiedzie, czy nie.

   -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.)

ale w tym przykładzie

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

Nie wypisuje niczego poza kodem wyjścia, który jest następnie powtarzany. To dane wyjściowe wykorzystuje sprawdzanie zmiennych. Wolę też, ponieważ jest to pojedyncza linia.

Możesz zamienić --silent na -q. Używam go, ponieważ nie jesteś zainteresowany wyjściem grep, tylko czy zadziałało, czy nie.

   -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
źródło
1

Prawidłowy sposób przypisania wyjścia polecenia grep do zmiennej jest taki, jak wspomniano @ monty-trudniej:

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

Aby przypisać status wyjścia tego polecenia do zmiennej, musisz użyć parametru powłoki $?zaraz po wykonaniu polecenia, jak pokazano poniżej:

grep -ci 'text' file.sh
check=$?
echo $check
Ciekawy
źródło