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.