Wie schreibe ich ein Bash-Skript, das optionale Eingabeargumente verwendet?


471

Ich möchte, dass mein Skript eine optionale Eingabe annehmen kann.

zB derzeit ist mein Skript

#!/bin/bash
somecommand foo

aber ich möchte es sagen:

#!/bin/bash
somecommand  [ if $1 exists, $1, else, foo ]

3
Bash oder POSIX? Mit Bash gibt es mehr Möglichkeiten
user123444555621

@ Pumbaa80 bash - Ich habe die Tags aktualisiert.
Abe


Antworten:


706

Sie können die Standardwertsyntax verwenden:

somecommand ${1:-foo}

Das Obige wird, wie im Bash-Referenzhandbuch - 3.5.3 Erweiterung der Shell-Parameter [Hervorhebung von mir] beschrieben:

Wenn der Parameter nicht gesetzt oder null ist , wird die Erweiterung des Wortes ersetzt. Andernfalls wird der Wert des Parameters ersetzt.

Wenn Sie einen Standardwert nur ersetzen möchten, wenn der Parameter nicht festgelegt ist (aber nicht, wenn er null ist, z. B. nicht, wenn es sich um eine leere Zeichenfolge handelt), verwenden Sie stattdessen diese Syntax:

somecommand ${1-foo}

Wieder aus dem Bash-Referenzhandbuch - 3.5.3 Erweiterung der Shell-Parameter :

Das Weglassen des Doppelpunkts führt zu einem Test nur für einen Parameter, der nicht festgelegt ist. Anders ausgedrückt, wenn der Doppelpunkt enthalten ist, prüft der Operator, ob beide Parameter vorhanden sind und ob ihr Wert nicht null ist. Wenn der Doppelpunkt weggelassen wird, prüft der Bediener nur die Existenz.


52
Beachten Sie den semantischen Unterschied zwischen dem obigen Befehl "return fooif $1is aset oder eine leere Zeichenfolge " und ${1-foo}"return fooif $1is aset".
10b0

12
Können Sie erklären, warum das funktioniert? Was ist speziell die Funktion / der Zweck des ':' und '-'?
jwien001

8
@ jwein001: In der oben angegebenen Antwort wird ein Substitutionsoperator verwendet, um einen Standardwert zurückzugeben, wenn die Variable undefiniert ist. Insbesondere lautet die Logik "Wenn $ 1 existiert und nicht null ist, geben Sie seinen Wert zurück; andernfalls geben Sie foo zurück." Der Doppelpunkt ist optional. Wenn es weggelassen wird, ändern Sie "existiert und ist nicht null" in nur "existiert". Das Minuszeichen gibt an, dass foo zurückgegeben werden soll, ohne dass $ 1 gleich 'foo' gesetzt wird. Substitutionsoperatoren sind eine Unterklasse von Expansionsoperatoren. Siehe Abschnitt 6.1.2.1 von Robbins und Beebes Classic Shell Scripting [O'Reilly] ( shop.oreilly.com/product/9780596005955.do )
Jubbles

5
@Jubbles oder wenn Sie nicht ein ganzes Buch für eine einfache Referenz kaufen möchten ... tldp.org/LDP/abs/html/parameter-substitution.html
Ohad Schneider

2
Diese Antwort wäre sogar noch besser, wenn sie zeigen würde, wie die Standardeinstellung als Ergebnis der Ausführung eines Befehls festgelegt wird, wie dies bei @hagen der Fall ist (obwohl diese Antwort unelegant ist).
Sautedman

310

Sie können einen Standardwert für eine Variable wie folgt festlegen:

somecommand.sh

#!/usr/bin/env bash

ARG1=${1:-foo}
ARG2=${2:-bar}
ARG3=${3:-1}
ARG4=${4:-$(date)}

echo "$ARG1"
echo "$ARG2"
echo "$ARG3"
echo "$ARG4"

Hier einige Beispiele, wie dies funktioniert:

$ ./somecommand.sh
foo
bar
1
Thu Mar 29 10:03:20 ADT 2018

$ ./somecommand.sh ez
ez
bar
1
Thu Mar 29 10:03:40 ADT 2018

$ ./somecommand.sh able was i
able
was
i
Thu Mar 29 10:03:54 ADT 2018

$ ./somecommand.sh "able was i"
able was i
bar
1
Thu Mar 29 10:04:01 ADT 2018

$ ./somecommand.sh "able was i" super
able was i
super
1
Thu Mar 29 10:04:10 ADT 2018

$ ./somecommand.sh "" "super duper"
foo
super duper
1
Thu Mar 29 10:05:04 ADT 2018

$ ./somecommand.sh "" "super duper" hi you
foo
super duper
hi
you

2
Ah, ok. Das hat -mich verwirrt (ist es negiert?).
Raffi Khatchadourian

5
Nein - das ist nur eine seltsame Art und Weise, wie Bash die Aufgabe erledigt. Ich werde noch einige Beispiele hinzufügen, um dies ein wenig zu verdeutlichen ... danke!
Brad Parks

44
if [ ! -z $1 ] 
then 
    : # $1 was given
else
    : # $1 was not given
fi

1
Technisch gesehen, wenn Sie eine leere Zeichenfolge '' übergeben, die möglicherweise als Parameter zählt, Ihre Prüfung jedoch verfehlt. In diesem Fall würde $ # sagen, wie viele Parameter angegeben wurden
vmpstr

18
-nist das gleiche wie ! -z.
10b0

Ich erhalte unterschiedliche Ergebnisse mit -nund ! -zdaher würde ich sagen, dass dies hier nicht der Fall ist.
Elieser

Da Sie die Variable nicht angegeben haben, [ -n $1 ] ist dies immer der Fall . Wenn Sie bash verwenden, [[ -n $1 ]]wird sich so verhalten, wie Sie es erwarten, andernfalls müssen Sie zitieren[ -n "$1" ]
Glenn Jackman

21

Sie können die Anzahl der Argumente mit überprüfen $#

#!/bin/bash
if [ $# -ge 1 ]
then
    $1
else
    foo
fi

10

Bitte vergessen Sie nicht, wenn die Variable $ 1 .. $ n ist, müssen Sie in eine reguläre Variable schreiben, um die Substitution zu verwenden

#!/bin/bash
NOW=$1
echo  ${NOW:-$(date +"%Y-%m-%d")}

2
Die obige Antwort von Brad beweist, dass Argumentvariablen auch ohne Zwischenvariablen ersetzt werden können.
Vadzim

2
+1 für die Angabe, wie ein Befehl wie Datum als Standard anstelle eines festen Werts verwendet werden kann. Dies ist auch möglich:DAY=${1:-$(date +%F -d "yesterday")}
Garren S

3

Für optionale Mehrfachargumente , analog zum lsBefehl, der eine oder mehrere Dateien aufnehmen kann, oder standardmäßig alles im aktuellen Verzeichnis auflistet:

if [ $# -ge 1 ]
then
    files="$@"
else
    files=*
fi
for f in $files
do
    echo "found $f"
done

Funktioniert leider nicht richtig für Dateien mit Leerzeichen im Pfad. Habe noch nicht herausgefunden, wie das funktioniert.


2

Dies ermöglicht den Standardwert für das optionale 1. Argument und behält mehrere Argumente bei.

 > cat mosh.sh
   set -- ${1:-xyz} ${@:2:$#} ; echo $*    
 > mosh.sh
   xyz
 > mosh.sh  1 2 3
   1 2 3 

1

Es ist möglich, die Variablensubstitution zu verwenden, dateum ein Argument durch einen festen Wert oder einen Befehl (wie ) zu ersetzen . Die Antworten haben sich bisher auf feste Werte konzentriert, aber dies ist, was ich verwendet habe, um Datum zu einem optionalen Argument zu machen:

~$ sh co.sh
2017-01-05

~$ sh co.sh 2017-01-04
2017-01-04

~$ cat co.sh

DAY=${1:-$(date +%F -d "yesterday")}
echo $DAY
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.