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

Otwórz drogę
źródło

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.

Tomasz
źródło
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
Poklepać
źródło
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.

Trampas Kirk
źródło
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.

Ryan Smith
źródło
$#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