2016-02-03 4 views
0

Может кто-нибудь объяснить мне, что означают эти выражения? Слишком тяжело для меня, интерпретируя это:

$(*:1:$#:1) 
$(*:1:$# - 1) 

Они используются в начале сценария:

!#/bin/bash 
file=${*:1:$#:1} 
egrep_command = `./generate_command $file ${*:1:$#-1} 

Я знаю, что последний параметр является именем файла, и я заинтересован, чтобы активировать generate_command по всем другим параметрам от первого до первого до последнего. Некоторые, как это должно делать то, что я сказал, я не понимаю весь синтаксис.

+5

Вы уверены, что это не '$ {*: 1: $ # - 1}'? – anishsane

+4

Слишком много опечаток в скрипте. Даже shebang ошибается. Это должно быть '#!', А не '! #'. Пробелы вокруг '=' в присваивании. Используйте http://www.shellcheck.net/ – anishsane

+0

нормально, но точка понятна, не так ли? Я имею в виду, что он должен делать. Точная правильность не в этом. – KittyT2016

ответ

3

Синтаксис в вопросе parameter expansion.

Приведенный скрипт пытается - плохо и неправильно - назначить последнюю переменную в своей командной строке file и передать остальные.

Ниже приведен вариант с наиболее очевидным тактическим (в отличие от стратегических) ошибок исправленных (хотя и с некоторыми предположениями о намерениях, так как это невозможно сказать, что глючит код был предназначено означать без описания человеческого языка) :

#!/bin/bash 

# assign last variable in "[email protected]" to file 
# This is taking the very last item in the list, by starting at the position named by the 
# total number of arguments 
file=${@:$#} 

# call generate_command with that file first, and all other arguments after 
egrep_command=$(./generate_command "$file" "${@:1:$#-1}") 

Даже с этими ошибками исправленных, это крайне неразумно кода: Если это хранить команду в переменном скаляре (строка), это склонное ко всем клопам, описанных в BashFAQ #50. (Если он намерен обойти некоторые из них с eval, то он также вводит уязвимости системы безопасности).

Кроме того, с помощью $* без кавычек, а не [email protected] внутри кавычек в исходном коде каскадного все выбранные аргументы вместе с пробелами - или, если переменная IFS была установлена, первый символ - между ними, а затем разбивают элементы возвращаются на части всякий раз, когда какой-либо символ в IFS (или, по умолчанию, вкладки, пробелы и символы новой строки) существовал, оценивая каждую фигуру как шаблон шара. Если вы не хотите, чтобы вся эта логика была выполнена, не используйте $* - используйте [email protected] и используйте ее внутри кавычек (кроме контекста, например, назначение переменной, где цитаты не нужны).


фокусировки на ПЭ, которая является основой вопроса:

"${@:start:len}" расширяется до len элементов, начиная с позиции start, из специального массива "[email protected]". Если у вас есть собственный массив, скажем, с именем arr, вы можете написать что-то подобное, как ${arr[@]:start:len}.

+1

Я боюсь, что '$ {@: len: start}' неверно, это '$ {@: start: len}' ... Соответственно, 'file = $ {@: 1: $ # - 1} 'будет назначать все переменные, кроме последних элементов; не последний элемент. Помимо этой ошибки и соответствующей ошибки в описании, ответ правильный. Кроме того, он предлагает правильное представление о многих хороших практиках. – anishsane

+0

@anishsane, спасибо; исправленный. –

Смежные вопросы