Чому пропуски між параметрами та параметрами можуть бути пропущені?


16

Наприклад:

xargs -n 1

те саме, що

xargs -n1

Але якщо ви подивитеся на сторінку чоловіка , параметр вказаний як -n max-args, що означає, що простір повинен бути збережений. Немає нічого про скорочену форму -n max-args .

Це також відбувається з багатьма іншими утилітами Linux.

Як це називається в Linux? Чи всі утиліти підтримують скорочену форму (але ніколи не документуйте її на довільній сторінці)?


1
12.1.2.a - частина історії; Я клянусь, що тут вже є хороший запитання щодо цього, але я його ще не знайшов.

2
@drewbenn інше питання, про яке ви думаєте, могло бути моїм: unix.stackexchange.com/q/188046/41515

Відповіді:


12

Коли ви пишете біт аналізу коду командного рядка вашого коду, ви вказуєте, які параметри беруть аргументи, а які ні. Наприклад, у скрипті оболонки, який приймає -hпараметр (наприклад, довідку) та -aпараметр, який повинен брати аргумент, ви робите

opt_h=0     # default value
opt_a=""

while getopts 'a:h' opt; do
    case $opt in
        h)  opt_h=1 ;;
        a)  opt_a="$OPTARG" ;;
    esac
done

echo "h: $opt_h"
echo "a: $opt_a"

a:hТрохи говорить : «Я очікую , щоб розібрати два варіанти, -aі -h, і -aповинен приймати аргумент» (це :після того, aщо говорить парсер , який -aприймає аргумент).

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

Запуск:

$ bash test.sh -h -a hello
h: 1
a: hello

$ bash test.sh -h -ahello
h: 1
a: hello

$ bash test.sh -hahello
h: 1
a: hello

Ось чому ви більшу частину часу не повинні писати власний аналізатор командного рядка для розбору варіантів.

На цьому прикладі є лише один випадок, який хитрий. Розбір зазвичай зупиняється на першою не-опції, тому якщо у вас є речі в командному рядку , яка виглядає як варіанти:

$ bash test.sh -a hello -world
test.sh: illegal option -- w
test.sh: illegal option -- o
test.sh: illegal option -- r
test.sh: illegal option -- l
test.sh: illegal option -- d
h: 0
a: hello

Наступне вирішує, що:

$ bash test.sh -a hello -- -world
h: 0
a: hello

Ці --сигнали кінець параметрів командного рядка, а -worldбіт залишається для програми , щоб зробити все , що хоче з (це в одній з позиційних змінних).

Тобто, до речі, як ви видалите файл, який має тире на початку свого імені файлу rm.

Редагувати :

Утиліти, написані на C-виклику getopt()(оголошені в unistd.h), які працюють майже так само. Насправді, наскільки ми знаємо, bashфункція getoptsможе бути реалізована за допомогою виклику функції C бібліотеки getopt(). У Perl, Python та інших мовах є аналогічні бібліотеки розбору командних рядків, і найімовірніше, що вони виконують їх аналіз аналогічним чином.

Деякі з цих getoptта getoptподібних процедур бібліотеки також обробляють "довгі" параметри. Вони , як правило , передує подвійним тир ( --) і довгими варіантами , які приймають аргументи часто робить це після знака рівності, наприклад --block-size=SIZEваріанту [деякі реалізації] в duкорисності (яка також дозволяє -B SIZEвказати те ж саме).

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

EDIT : Дійсно старі інструменти, такі , як ddі tarутиліти, є варіанти без тиру перед ними. Це виключно з історичних причин та для підтримки сумісності з програмним забезпеченням, яке покладається на них, щоб вони працювали саме таким чином. tarУтиліта отримала можливість приймати варіанти з прочерками в більш пізні часи. Посібник BSD для tarвиклику старих варіантів стилів для "пакетних прапорів".


Ця функція може здатися простою у застосуванні в баш-сценаріїв. Але я думаю, що більшість утиліт написані на C (потім компільовані у двійкові файли), а не в bash. Чому ці утиліти реалізують цю функцію?
Дж. Джо

@ J.Joe Тому, що вони дзвонять getopt()(оголошено в unistd.h), що робить те саме.
Kusalananda

2
Так, ви праві. Довідково . Це також вирішує ще одну таємницю, що варіанти можна комбінувати -a -b=== -ab
Дж. Джо

1
Необов’язкові аргументи для прапорів створювали б неоднозначність, тому їх не можна поєднувати (якщо -aє необов'язковий аргумент, -abне те саме, що -a -b). GNU getopt не зупиняє обробку прапорів при зустрічі з непрапортом: натомість (за замовчуванням), замість цього вона переставляє прапори на передню частину argv.
ilkkachu

@ilkkachu Дякую за пояснення. Я можу оновити свою відповідь пізніше.
Kusalananda

4

xargsє однією з утиліт POSIX. Як зауважив @drewbenn, POSIX документує поведінку синтаксичного аналізу більшості своїх утиліт getopt, з деякими дозволами для інших реалізацій, сказано в 12.1 Синтаксис аргументу утиліти :

Цей розділ описує синтаксис аргументів стандартних утиліт та вводить термінологію, яка використовується у POSIX.1-2008 для опису аргументів, оброблених утилітами.

У POSIX.1-2008 для опису синтаксису аргументів утиліти використовується спеціальне позначення. Якщо не зазначено інше , усі описи утиліт використовують це позначення, що проілюстровано цим прикладом (див. Прості команди XCU ):

і закінчуючи с

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

У POSIX (пам’ятайте, що він охоплює лише найбільш часто використовувані утиліти), є винятки, які передають операнди, які були б опціями в інших утилітах як позиційні параметри, так і параметри зі спеціальним синтаксисом :

POSIX дозволяє отримати необов'язкові параметри-значення:

Параметри-аргументи відображаються відокремленими від їх параметрів <blank>символами, за винятком випадків, коли параметр-аргумент вкладений у нотацію '['та ']'позначення, що вказує, що це необов'язково.

Я не пригадую, які POSIX утиліти використовують цю функцію. У Ncurses ticі infocmpутиліти використовують цю функцію для рівнів в -v(інформативному / налагодженні) варіанту.

Конкретний пункт, про який ви запитували, детально описується в решті цього параграфа, виходячи з кількох рядків.

Перед POSIX, деякі реалізації psприйнятих варіантів без провідного дефісу. В описі POSIX не зазначається, що в описі утиліти або в синтаксичному обгрунтуванні:

Крім POSIX, існує реалізація з довгими опціями (наприклад, GNU getopt_long або X Toolkit ), використовуючи різні способи розділення або приєднання значення параметра до параметра. Наприклад, розділові знаки можуть бути використані:

--option=value
--option value

Залежно від реалізації, подвійний тире може / не може використовуватися для відмежування довгих варіантів від коротких (getopt): рись та X Toolkit використовують один тире; getopt_longНаприклад, GNU використовує подвійний тире. Також +може бути використаний знак, який вказує на те, що параметр відхилено.

В описі POSIX не згадується жодне з них, але ви, безсумнівно, стикаєтеся з ними.


Є чи -option=valueповинен бути --option=value(довгий формат-варіанту, два тири на початку , а не один)?
J.Joe

Деякі застарілі утиліти використовують однозначні довгі параметри (-опція), але вони значно застаріли для нових сценаріїв та програм. Використовуйте один тире для коротких варіантів, якими обробляє getopt. Майже у всіх нових сценаріях та програмах використовуються довгі параметри з подвійним штрихом. Багато людей також підтримують однозначні еквіваленти коротких варіантів для найбільш часто використовуваних. Довгі варіанти роблять код скрипту набагато більш самодокументованим, потребуючи меншої кількості коментарів.
DocSalvager
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.