Поясніть команду оболонки: shift $ (($ optind - 1))


30

Я не хлопець Linux, але застряг у якомусь сценарії, який я повинен прочитати для свого проекту. Тож чи може хтось допомогти мені, що робить ця команда?

shift $(($optind - 1))

3
Як зазначено нижче, OPTIND має бути в верхньому регістрі, а "$" всередині дужок необов'язково.
DarkHeart

Відповіді:


49

shift $((OPTIND-1))(Примітка OPTIND- це верхній регістр), як правило, знаходиться відразу після getopts whileциклу. $OPTIND- кількість варіантів, знайдених користувачем getopts.

Як згадує pauljohn32 в коментарях, строго кажучи, OPTINDдає позицію наступного аргументу командного рядка.

З довідника керівництва GNU Bash :

ім'я оптимізації getopts [args]

getoptsвикористовується скриптами оболонки для розбору позиційних параметрів. optstringмістить символи опцій, які слід розпізнати; якщо за символом слідує двокрапка, очікується, що параметр має аргумент, який повинен бути відокремлений від нього пробілом. Двокрапка (':') та знак питання ('?') Не можуть використовуватися як символи опції. Кожен раз, коли він викликається, getoptsрозміщує наступний параметр у назві змінної оболонки, ініціалізуючи, nameякщо його не існує, та індекс наступного аргументу, який обробляється у змінну OPTIND. OPTINDініціалізується до 1 кожного разу, коли викликається оболонка або сценарій оболонки. Коли для параметра потрібен аргумент, getopts розміщує цей аргумент у змінній OPTARG. Оболонка не скидаєтьсяOPTIND автоматично; він повинен бути вручну скинутий між декількома викликами в getoptsмежах одного виклику оболонки, якщо потрібно використовувати новий набір параметрів.

Коли зустрічається кінець опцій, getoptsвихід із значенням повернення більше нуля. OPTINDвстановлюється в індексі першого аргументу, що не є опцією, а ім'я - "?".

getoptsзазвичай аналізує позиційні параметри, але якщо введено більше аргументів args, то getoptsзамість них аналізуємо.

shift n
видаляє n рядків зі списку позиційних параметрів. Таким чином, shift $((OPTIND-1))видаляються всі параметри, які були проаналізовані getoptsзі списку параметрів, і тому після цього пункту $1буде посилатися на перший аргумент без опцій, переданий до сценарію.

Оновлення

Як згадує mikeserv у коментарі, shift $((OPTIND-1))може бути небезпечним. Для запобігання небажаного розбиття слів і т. Д. Всі розширення параметрів повинні бути подвійними. Тож безпечною формою для команди є

shift "$((OPTIND-1))"


Здається, що це спрацює правильно лише в тому випадку, якщо всі параметри відбудуться до будь-яких інших позиційних аргументів. Правильно?
Стів Йоргенсен

@SteveJorgensen: Так, це правильно. OTOH, розміщення варіантів після необов'язкових аргументів суперечить умові sh / bash. Як правило, перші аргументи, які не починаються з тире, означають кінець параметрів, а всі наступні аргументи, які починаються з тире, не вважаються варіантами. Не всі програми дотримуються цієї конвенції, але це робить життя набагато простішим, якщо ви це робите. :)
PM 2Ring

@SteveJorgensen: (продовження) Ця тема коротко обговорюється у розділі Чому деякі утиліти розбирають операнди перед параметрами? . Як згадується в коментарі Жилла до відповіді Селади, деякі програми (як find) можуть виглядати так, що вони дозволяють варіанти після не-варіантів, але вони ні: у них є операнди, які починаються з тире.
PM 2Ring

Дякую за цю інформацію (і редагування) @mosvy Це досить незвично IFS, але краще бути в безпеці, ніж вибачити. ;)
PM 2Ring

@roaima якщо IFS=0123456789, shift $((OPTIND-1))(без лапок) перетвориться в shift ""який буде проігнорована (в ksh) або генерувати помилку (в bashі dash).
mosvy

8

$((...))просто обчислює речі. У вашому випадку він приймає значення $optintта субстрати 1.

shiftвидаляє позиційні параметри. У вашому випадку він видаляє optint-1параметри.

Для отримання додаткової інформації подивіться на help getopts, help shift, погляд на man bashдля «Арифметика розширення», і особливо Google для getopts.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.