Bash, ostrzeżenie o braku argumentów i decyzje w sprawie


110

Uczę się basha.

Chciałbym zrobić prosty skrypt, który bez podania argumentów pokazuje jakiś komunikat. A kiedy podaję liczby jako argumenty, zależnie od wartości, robi to jedno lub drugie.

Chciałbym również poznać sugestie dotyczące najlepszych podręczników online dla początkujących w bash

Dzięki

Odpowiedzi:


176
if [[ $# -eq 0 ]] ; then
    echo 'some message'
    exit 0
fi

case "$1" in
    1) echo 'you gave 1' ;;
    *) echo 'you gave something else' ;;
esac

Przewodnik po zaawansowanych skryptach Bash jest całkiem niezły. Pomimo swojej nazwy traktuje podstawy.


RE: "wyjście 0". Nie wiem, czy miał na myśli wyjście ze scenariusza. Ale tak, to doskonały przewodnik.
Trampas Kirk

Zinterpretowałem „i” jako „inaczej”, zakładając, że wiadomość będzie tekstem pomocy. Ale jestem pewien, że Werner jest w stanie dowiedzieć się, co robi ta linia i czy tego chce :)
Thomas

dzięki, oczywiście! i ostatnia rzecz, jak mogę wyłączyć komunikaty o błędach w skrypcie, aby nie były wyświetlane w powłoce?
Otwórz drogę

Masz na myśli błędy wychodzące z określonego programu, który wywołujesz? Możesz umieścić > /dev/nulli / lub 2> /dev/nullpóźniej, aby wysłać jego standardowe wyjście i / lub standardowe strumienie błędów w zapomnienie.
Thomas

4
Jeśli uznasz brakujący argument za coś złego (np. Skrypt nie może działać poprawnie), zwróć coś innego niż 0 ( exit 1). Istnieją inne konwencje dotyczące kodów powrotu / wyjścia, które można szybko znaleźć w Internecie, ale ważne jest, aby nie było 0, co wskazuje na sukces.
Felix

25

Jeśli interesuje Cię tylko bailing, jeśli brakuje określonego argumentu, podstawianie parametrów jest świetne:

#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT

11

Przykład

 if [ -z "$*" ]; then echo "No args"; fi

Wynik

No args

Detale

-z jest operatorem jednoargumentowym dla długości łańcucha równej zero. $*to wszystkie argumenty. Cudzysłowy są dla bezpieczeństwa i zawierają wiele argumentów, jeśli są obecne.

Użyj man bashi wyszukaj ( klawisz / ) „jednoargumentowy”, aby znaleźć więcej takich operatorów.


7
(Drobny) problem polega na tym, że nie rozróżnia między przekazywaniem żadnych argumentów a przekazaniem pustego ciągu jako argumentu. Może to być ważne w niektórych kontekstach. Używając [$ # -eq 0] można poprawnie obsłużyć oba przypadki.
Idelic

1
Ach, subtelności programowania (ba) sh ... Dlatego go nienawidzę.
Thomas

1
pomyśl -zjako mizzing
Ray Foss

4

Stara, ale mam powód, aby teraz zmienić odpowiedź dzięki pewnym wcześniejszym nieporozumieniom:

if [[ $1 == "" ]] #Where "$1" is the positional argument you want to validate 

 then
 echo "something"
 exit 0

fi

Powoduje to echo „Coś”, jeśli nie ma argumentu pozycyjnego $ 1. Nie sprawdza jednak, czy $ 1 zawiera określone informacje.


$#jest jawnie całkowitą liczbą argumentów; będzie to albo „0”, a powtórzysz „coś”, nawet jeśli nie ma argumentów, albo będzie to jakaś liczba dodatnia i poprawnie powtórzysz „coś”. Ale samo sprawdzenie nigdy nic nie da, niezależnie od danych wejściowych lub braku danych wejściowych, których używasz - zawsze zgłosi, że $#zawiera wartość. Jest to więc całkowicie błędne i nigdy nie będzie działać zgodnie z twierdzeniami.
eschwartz

Czy jesteś tego całkowicie pewien? Mam kilka skryptów, które działają zgodnie z przeznaczeniem, używając dokładnie tego formatu. Po przeczytaniu twojej odpowiedzi ponownie przetestowałem nawet dopasowanie i jego brak. $ # nie będzie zawierało wartości, jeśli nie zostanie określone, jeśli nie ma argumentu pozycyjnego, który pasowałby do tego, co kiedykolwiek # jest w twoim scenariuszu. Nie ma sensu, dlaczego bash miałby przyjmować wartość w argumencie pozycyjnym, którego nie ma.
Ryan Smith

Spróbuj echo $#jak zawartości /tmp/test.sh skryptu, a następnie uruchomić go w katalogu / bin / bash, jak / bin / sh (lub / bin / dash i cokolwiek innych implementacjach powłoki masz dostępne. /tmp/test.shEcho „0” konsola, zgodnie z wolą /bin/dash /tmp/test.sh. Z drugiej strony, /tmp/test.sh foo/tmp/test.sh first second
odbije się

Zgodnie man bashz rozdziałem „Parametry specjalne”, „Powłoka traktuje kilka parametrów w specjalny sposób. Do tych parametrów można się odwoływać tylko; przypisywanie do nich jest niedozwolone.” I „# Interpretacja do liczby parametrów pozycyjnych w postaci dziesiętnej”. Jest to również wymagane przez POSIX, jak opisano w pubs.opengroup.org/onlinepubs/9699919799/utilities/ ...
eschwartz

Przepraszamy, wygląda na to, że wystąpił błąd w komunikacji! Miałem na myśli # jako symbol zastępczy dla określonego argumentu pozycyjnego (tj. 2 $, jeśli miałeś na myśli drugi argument), a nie dosłownie $ #. Po przejrzeniu powyższego masz absolutną rację, dosłowny $ # zawsze odpowiada liczbie argumentów. Przepraszamy za zamieszanie.
Ryan Smith
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.