Як я можу використовувати $ *, опускаючи вхідні змінні певних змінних, таких як $ 1 і $ 2?


15

Наприклад,

elif [[ $append = $1 ]]
then
  touch ~/directory/"$2".txt
  echo "$variable_in_question" >> ~/directory/"$2".txt

або створити текстовий файл, що містить усі вхідні дані "$2", або додати існуючий текстовий файл із усім введенням наступним "$2", що я використовував би замість "$variable_in_question"рядка 4?

Я в основному хочу "$*", але пропускаю "$1"і "$2".

Відповіді:


32

Ви можете використовувати bashРозширення параметрів, щоб вказати діапазон, це працює і з позиційними параметрами. Бо $3$nбуло б:

"${@:3}" # expands to "$3" "$4" "$5" …
"${*:3}" # expands to "$3 $4 $5 …"

Майте на увазі, що і те, $@і $*ігноруйте перший аргумент $0. Якщо вам цікаво, який з них використовувати у вашому випадку: дуже ймовірно, що ви хочете, щоб котирувались $@. Не використовуйте, $*якщо ви прямо не хочете, щоб аргументи цитувалися окремо.

Ви можете спробувати так:

$ bash -c 'echo "${@:3}"' 0 1 2 3 4 5 6
3 4 5 6
$ echo 'echo "${@:3}"' >script_file
$ bash script_file 0 1 2 3 4 5 6
2 3 4 5 6

Зауважте, що в першому прикладі $0заповнюється перший аргумент, 0тоді як при використанні в сценарії $0замість нього заповнюється ім'я сценарію, як показує другий приклад. Ім'я сценарію, bashзвичайно, є першим аргументом, просто те, що воно зазвичай не сприймається як таке - те саме стосується і сценарію, виконаного виконуваним, і називається "безпосередньо". Отже, у першому прикладі маємо $0= 0, $1= 1тощо, тоді як у другому - $0= script_file, $1= 0, $2= 1тощо; ${@:3}вибирає кожен аргумент, починаючи з $3.

Деякі додаткові приклади можливих діапазонів:

 # two arguments starting with the third
$ bash -c 'echo "${@:3:2}"' 0 1 2 3 4 5 6
3 4
 # every argument starting with the second to last one
 # a negative value needs either a preceding space or parentheses
$ bash -c 'echo "${@: -2}"' 0 1 2 3 4 5 6
5 6
 # two arguments starting with the fifth to last one
$ bash -c 'echo "${@:(-5):2}"' 0 1 2 3 4 5 6
2 3

Подальше читання:


27

Ви можете використовувати shiftвбудований:

$ help shift
shift: shift [n]
    Shift positional parameters.

    Rename the positional parameters $N+1,$N+2 ... to $1,$2 ...  If N is
    not given, it is assumed to be 1.

    Exit Status:
    Returns success unless N is negative or greater than $#.

Вих. дано

$ cat argtest.bash 
#!/bin/bash

shift 2

echo "$*"

потім

$ ./argtest.bash foo bar baz bam boo
baz bam boo

3
@Oreoplasm Я думаю, що варто згадати, що shiftпідхід унеможливить доступ $1і $2після того, як ви їх змістили. У своєму сценарії, який ви використовуєте $2поряд із $variable_in_question, вам потрібно змінити це або використовувати підхід Розширення параметрів.
десерт

6
shiftце добре , коли перший один або більше арг особливий і це має сенс , щоб забрати їх в окремі змінні ( foo="$1"; bar="$2";або if [[ something with $1 ]];then blah blah; shift. Але @ відповіді десерту з неразрушающим підходом хороший в інших випадках , коли ви дійсно все ще хочете повний список пізніше або коли ви використовуєте більш симпатичний синтаксис для вибору обмеженого діапазону аргументів, не до нескінченності, без введення порожніх аргументів у команду, якщо $@не так багато елементів.
Пітер Кордес,

13

Як правило, ви можете скопіювати позиційні параметри в масив, видалити довільні індекси масиву, а потім використовувати масив для розширення саме до тих індексів, які ви хочете, не втрачаючи початкових аргументів.

Наприклад, якщо я хотів усі аргументи, крім першої, четвертої та п’ятої:

args=( "$@" )
unset args[0] args[3] args[4]
echo "${args[@]}"

У копії індекси зміщуються на 1, оскільки $0не є частиною $@.


1
Звичайно, можна поєднувати це, наприклад, echo "${args[@]:2}"для третього до останнього аргументу.
десерт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.