Próbuję napisać funkcję w bash, która będzie miała dostęp do argumentów wiersza poleceń skryptów, ale są one zastępowane argumentami pozycyjnymi funkcji. Czy istnieje sposób, aby funkcja uzyskała dostęp do argumentów wiersza poleceń, jeśli nie są one jawnie przekazywane?
# Demo function
function stuff {
echo $0 $*
}
# Echo's the name of the script, but no command line arguments
stuff
# Echo's everything I want, but trying to avoid
stuff $*
bash
command-line-arguments
argv
DonGar
źródło
źródło
$*
jest bardzo błędny - zmieni./yourScript "first argument" "second argument"
się./yourscript "first" "argument" "second" "argument"
lub zmieni./yourscript '*.txt'
na coś podobnego./yourscript one.txt two.txt
pomimo cytatów.Odpowiedzi:
Czytając podręcznik bash ref mówi, że ten materiał jest przechwytywany w BASH_ARGV, chociaż dużo mówi o „stosie”.
#!/bin/bash function argv { for a in ${BASH_ARGV[*]} ; do echo -n "$a " done echo } function f { echo f $1 $2 $3 echo -n f ; argv } function g { echo g $1 $2 $3 echo -n g; argv f } f boo bar baz g goo gar gaz
Zapisz w f.sh
źródło
Jeśli chcesz mieć swoje argumenty w stylu C (tablica argumentów + liczba argumentów), możesz użyć
$@
i$#
.$#
podaje liczbę argumentów.$@
podaje wszystkie argumenty. Możesz przekształcić to w tablicę przezargs=("$@")
.Na przykład:
args=("$@") echo $# arguments passed echo ${args[0]} ${args[1]} ${args[2]}
Zauważ, że w
${args[0]}
rzeczywistości jest to pierwszy argument, a nie nazwa twojego skryptu.źródło
args
tablicy z wnętrza funkcji, jeśli wcześniej ją zainicjujesz, jak opisano.echo "${args[0]} ${args[1]} ${args[2]}"
lub argumenty podlegają rozszerzaniu nazw plików.#!/usr/bin/env bash echo name of script is $0 echo first argument is $1 echo second argument is $2 echo seventeenth argument is $17 echo number of arguments is $#
Edycja: zobacz mój komentarz do pytania
źródło
Komentarz Raviego jest w istocie odpowiedzią. Funkcje przyjmują własne argumenty. Jeśli chcesz, aby były takie same jak argumenty wiersza poleceń, musisz je przekazać. W przeciwnym razie wyraźnie wywołujesz funkcję bez argumentów.
To powiedziawszy, możesz, jeśli chcesz, przechowywać argumenty wiersza poleceń w globalnej tablicy do użycia w innych funkcjach:
my_function() { echo "stored arguments:" for arg in "${commandline_args[@]}"; do echo " $arg" done } commandline_args=("$@") my_function
Musisz uzyskać dostęp do argumentów wiersza poleceń poprzez
commandline_args
zmienną, nie$@
,$1
,$2
, itd., Ale są one dostępne. Nie znam żadnego sposobu, aby przypisać bezpośrednio do tablicy argumentów, ale jeśli ktoś ją zna, proszę mnie oświecić!Zwróć także uwagę na sposób, w jaki użyłem i zacytowałem
$@
- w ten sposób możesz upewnić się, że znaki specjalne (białe spacje) nie zostaną zepsute.źródło
# Save the script arguments SCRIPT_NAME=$0 ARG_1=$1 ARGS_ALL=$* function stuff { # use script args via the variables you saved # or the function args via $ echo $0 $* } # Call the function with arguments stuff 1 2 3 4
źródło
Można to również zrobić w ten sposób
#!/bin/bash # script_name function_test.sh function argument(){ for i in $@;do echo $i done; } argument $@
Teraz wywołaj swój skrypt w stylu
źródło
function print() {
jest połączeniem dwóch różnych form deklaracji funkcji -function print {
co jest starszą składnią ksh, która jest obsługiwana przez bash w celu zapewnienia kompatybilności wstecznej z pre-POSIX (czyli sprzed 1991 r.) ksh iprint() {
, która jest standaryzowana zgodnie z POSIX. Rozważ użycie jednej lub drugiej, aby uzyskać większą kompatybilność z innymi powłokami; zobacz także wiki.bash-hackers.org/scripting/obsoleteMożesz użyć słowa kluczowego shift (operator?), Aby je iterować. Przykład:
#!/bin/bash function print() { while [ $# -gt 0 ] do echo $1; shift 1; done } print $*;
źródło
function print() {
jest połączeniem dwóch różnych form deklaracji funkcji -function print {
co jest starszą składnią ksh, która jest obsługiwana przez bash w celu zapewnienia kompatybilności wstecznej z pre-POSIX (czyli sprzed 1991 r.) ksh iprint() {
, która jest standaryzowana zgodnie z POSIX. Rozważ użycie jednej lub drugiej, aby uzyskać większą kompatybilność z innymi powłokami; zobacz także wiki.bash-hackers.org/scripting/obsoleteMoje rozwiązanie:
Utwórz skrypt funkcji, który jest wywoływany wcześniej niż wszystkie inne funkcje bez przekazywania do niego żadnych argumentów, na przykład:
Następnie możesz wywołać init i użyć zmiennej ORIGOPT w razie potrzeby, jako plus, zawsze przypisuję nową zmienną i kopiuję zawartość ORIGOPT do moich nowych funkcji, dzięki czemu możesz mieć pewność, że nikt nie będzie go dotykał lub Zmień to.
Dodałem spacje i myślniki, aby ułatwić parsowanie go za pomocą 'sed -E', a także bash nie przekaże go jako odniesienia i sprawi, że ORIGOPT będzie rosnąć, gdy wywoływane są funkcje z większą liczbą argumentów.
źródło