Итерация по значениям $@

Я хотел бы перебрать аргументы, данные скрипту bash, например:

./bash_script file1 file2 file3

$@ дает мне все файлы, предоставленные сценарию, но как мне перебрать файлы?

я бы хотел cat каждый файл и удалить содержимое с помощью awk (Я знаю, как это сделать, это распаковка $@ это меня смутило)

2 ответа

Решение

Хитрость заключается в двойной кавычке, как в "$@",

foo(){
   printf ' ->%s\n' "$@";
}
foo "a b" c "d e"

эквивалентно:

printf ' ->%s\n' "a b" c "d e"

Если $@ в вышесказанном не стоит двойных кавычек, тогда вы получите:

 printf ' ->%s\n' a b c d e

из-за разделения слов на $IFS персонажи ($IFS по умолчанию ' '$'\t'$'\n'пробел, табуляция и перевод строки)


$@ против $*

Двойные кавычки работают следующим образом для любого @-расширения в любом массиве:

$ foo=( "a b" c "d e" )
$ printf ' ->%s\n' "${foo[@]}"
   ->a b
   ->c
   ->d e

В отличие от * расширения (например, $*, ${foo[*]}) будет использовать первый символ $IFS объединить элементы массива в одну строку:

$ foo=( "a b" c "d e" )
$ ( IFS=:; printf ' ->%s\n' "${foo[*]}" )
 ->a b:c:d e

который, если оставить его без кавычек, снова разделится на этот самый символ IFS:

$ foo=( "a b" c "d e:f:g" )
$ ( IFS=:; printf ' ->%s\n' ${foo[*]} ) 
 ->a b
 ->c
 ->d e
 ->f
 ->g

Трюк для итерации по $@ в циклах for:

"$@" массив особенный. Если вы хотите перебрать "$@" в цикле, то вы можете сократить

 for variable_name in "$@"; do
   ...
 done

как

 for variable_name; do 
 done

как пропустить in something часть for цикл подразумевает in "$@",

Это работает даже в оболочках только для POSIX (dash, bourne shell), которые не имеют переменных массива, но поддерживают "$@" а также "$*,

Чтобы перебрать их, вы используете двойные кавычки $@вдоль линий:

for arg in "$@" ; do
    echo "--> ${arg}"
done

for arg in "$@" также может быть написано как for arg (или даже for arg in) так как bash Страница руководства гласит:

for name [ [ in [ word ... ] ] ; ] do list ; done

бла бла бла

Если слово in опущено, команда for выполняет список один раз для каждого установленного позиционного параметра.

Однако я предпочитаю явный вариант.

Следующая стенограмма показывает это в действии:

pax: testprog.sh 1 2 3 '4 5' '' '6 7 8' "9"
--> 1
--> 2
--> 3
--> 4 5
--> 
--> 6 7 8
--> 9

И, как в сторону, ваш комментарий об использовании cat а также awk изменение файлов может обрушить гнев "бесполезного использования cat Награда "Толпа":-)

Если вы думаете о чем-то вроде:

cat "${fspec}" | awk 'do something'

затем cat совершенно ненужно. Вместо этого вы можете использовать:

awk 'do something' "${fspec}"

Я обычно не беспокоюсь о (небольшой) неэффективности запуска дополнительного процесса, но некоторые люди делают.

Другие вопросы по тегам