запутанный оператор в сценарии командной строки

#bash #shell #unix

#bash #оболочка #unix

Вопрос:

 while sizes=`sizes $pgid`
do
    set -- $sizes
    sample=$((${@/#/ }))
    let peak="sample > peak ? sample : peak"
    sleep 0.1
done
  

меня смущает приведенное ниже утверждение:

 sample=$((${@/#/ }))
  

кто-нибудь может это объяснить?

Ответ №1:

Часть ‘ ${@/#/ } ‘ является расширением регулярного выражения:

 ${parameter/pattern/string}
  

Шаблон расширяется для создания шаблона точно так же, как при расширении имени файла.
Параметр расширен, и самое длительное совпадение шаблона с его значением равно
заменено на string. Если шаблон начинается с ‘ / ‘, все совпадения с шаблоном заменяются
с помощью строки. Обычно заменяется только первое совпадение. Если шаблон начинается
с помощью ‘ # ‘ оно должно совпадать с началом расширенного значения параметра.
Если шаблон начинается с ‘ % ‘, он должен совпадать в конце развернутого значения
параметр. Если строка равна null, совпадения с шаблоном удаляются и / следующий
шаблон может быть опущен. Если параметр равен ‘ @ ‘ или ‘ * ‘, операция подстановки
применяется к каждому позиционному параметру по очереди, и результатом является расширение
список. Если параметр является переменной массива, подписанной ‘ @ ‘ или ‘ * ‘, то
операция подстановки применяется к каждому элементу массива по очереди, и
расширение — это результирующий список.

Итак, похоже, что он заменяет пустую строку в начале каждого значения в списке аргументов ‘ $@ ‘ на ‘ ‘. Его ключевым достоинством является то, что он добавляет префикс к каждому аргументу одним махом; в остальном он похож на " $var" .


Часть ‘ $(( ... )) является арифметическим выражением. Он выполняет арифметику над выражением, заключенным в круглые скобки. Итак, в контексте он суммирует значения в списке аргументов, предполагая, что все они числовые. Учитывая расширение, это может привести:

 set -- 2 3 5 7 11
sample=$((${@/#/ }))
sample1=$(( 2  3  5  7  11))
echo $sample = $sample1
  

и, следовательно, ‘ 28 = 28 ‘.

Ответ №2:

Давайте рассмотрим строку изнутри наружу.

 ${@/#/ }
  

Это расширение параметра, которое расширяет $@ параметр (который в данном случае будет массивом всех элементов в $sizes ), а затем выполняет сопоставление шаблона для каждого элемента, заменяя каждую сопоставленную последовательность на . # В шаблоне соответствует началу каждого элемента во входных данных; фактически он ничего не использует, поэтому замена на просто добавит перед каждым элементом. Вы можете увидеть это в действии с помощью простой тестовой функции:

 $ function tst() { echo ${@/#/ }; }
$ tst 1 2 3
 1  2  3
  

Результат этого затем подставляется в $(( )) , который выполняет арифметическое расширение, вычисляя выражение внутри него. Конечным результатом является то, что переменной $sample присваивается значение суммы всех чисел в $sizes .

Ответ №3:

Это арифметическое расширение замены строки.

$(( )) является арифметическим расширением — например echo $((1 2)) . ${var/x/y} является заменой строки; в этом случае замените первую # в строке на . $@ это переменная, которая в данном случае содержит $sizes; это заменит строку, а затем, похоже, добавит в нее значения.

Комментарии:

1. Нет, он не заменит первый # на , # в шаблоне ${var/pat/string} замена будет соответствовать началу каждого элемента в var , поэтому он добавит к началу элемента в $@ .

Ответ №4:

${var/old/new} расширяет $ var, изменяя любое «старое» на «новое». ${var/#old / new} настаивает на том, чтобы совпадение начиналось с начала значения $ {var/#/new}, заменяемого в начале каждой переменной $ {@/ #/new} (и $ @), применяется к каждому параметру

$(( 1 3 )) заменяется арифметическим результатом.

$(( ${@/#/ / ))

Расширяет $@, аргументы из set — $sizes, добавляет » » к каждому параметру и выполняет результат с помощью арифметического вычисления. Похоже, что он добавляет все значения в каждой строке.