Bash: Почему используются eval и shift в скрипте, который анализирует аргументы командной строки?

Вы можете увидеть текущий доступ к файлу с помощью команды list open files, lsof. Ниже приведены примеры вывода.

# lsof

COMMAND  PID       USER   FD      TYPE     DEVICE  SIZE/OFF       NODE NAME
init       1       root  cwd       DIR        8,1      4096          2 /
init       1       root  txt       REG        8,1    124704     917562 /sbin/init
init       1       root    0u      CHR        1,3       0t0       4369 /dev/null
init       1       root    1u      CHR        1,3       0t0       4369 /dev/null
init       1       root    2u      CHR        1,3       0t0       4369 /dev/null
init       1       root    3r     FIFO        0,8       0t0       6323 pipe

Пример 2 - +D = рекурсивный:

# lsof +D /var/log/

COMMAND   PID   USER  FD   TYPE DEVICE SIZE/OFF   NODE NAME
rsyslogd  488 syslog   1w   REG    8,1     1151 268940 /var/log/syslog
rsyslogd  488 syslog   2w   REG    8,1     2405 269616 /var/log/auth.log
console-k 144   root   9w   REG    8,1    10871 269369 /var/log/ConsoleKit/history

Man lsof даст вам несколько дополнительных примеров.

4
08.11.2018, 23:15
2 ответа

Одна из многих вещей, которые getoptделает при синтаксическом анализе параметров, заключается в переупорядочении аргументов, так что аргументы, не являющиеся -параметрами, идут последними, а комбинированные короткие параметры разделяются. Изman getopt:

Output is generated for each element described in the previous section.
Output is done in the same order as the elements are specified  in  the
input,  except  for  non-option  parameters.   Output  can  be  done in
compatible (unquoted) mode, or in such way that  whitespace  and  other
special  characters  within  arguments  and  non-option  parameters are
preserved (see QUOTING).  When the output is  processed  in  the  shell
script,  it  will  seem to be composed of distinct elements that can be
processed one by  one  (by  using  the  shift  command  in  most  shell
languages).

[...]

Normally, no  non-option  parameters  output  is  generated  until  all
options  and  their  arguments  have  been  generated.   Then  '--'  is
generated as a single parameter, and after it the non-option parameters
in  the  order  they were found, each as a separate parameter.

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

Таким образом, TEMPсодержит переставленные, заключенные в кавычки, разделенные -параметры, и использование eval setделает их аргументами сценария.

Почему eval? Вам нужен способ безопасного преобразования вывода getoptв аргументы. Это означает безопасную обработку специальных символов, таких как пробелы, ', "(, кавычки, ), *и т. д. Для этого getoptэкранирует их в выводе для интерпретации оболочкой. Без evalединственным вариантом является set $TEMP,но вы ограничены тем, что возможно, путем разделения полей и подстановки вместо полной возможности синтаксического анализа оболочки.

Допустим, у вас есть два аргумента. Невозможно получить эти два слова как отдельные слова, используя только разделение полей без дополнительного ограничения символов, используемых в аргументах (, например, скажем, вы установили IFS в :, тогда вы не можете иметь :в аргументах ). Таким образом, вам нужно иметь возможность экранировать такие символы и интерпретировать это экранирование оболочкой, поэтому evalнеобходим. За исключением серьезной ошибки в getopt, это должно быть безопасно.


Что касается shift, то он делает то же, что и всегда :удаляет первый аргумент и сдвигает все аргументы (так, что то, что было $2, теперь будет$1). Это устраняет аргументы, которые были обработаны, так что после этого цикла остаются только аргументы опции, отличные от -, и вы можете удобно использовать $@, не беспокоясь об опциях.

10
27.01.2020, 20:50

Скрипт работает правильно, когда выдает ошибку -a 10. Опция -aне нуждается в параметре в этом скрипте. Вы должны использовать только -a.

Сдвиг описан на справочной странице следующим образом:

shift [n]
              The positional parameters from n+1... are renamed to $1....  Parameters represented by the numbers $# down to $#-n+1 are unset.  n must be a non-negative number less than or equal to $#.  If  n  is
              0,  no  parameters are changed.  If n is not given, it is assumed to be 1.  If n is greater than $#, the positional parameters are not changed.  The return status is greater than zero if n is greater
              than $# or less than zero; otherwise 0.

Таким образом, в основном он отбрасывает -a и сдвигает оставшиеся аргументы, так что второй параметр будет равен $1 в следующем цикле.

--также описано на справочной странице :

.
 --        A -- signals the end of options and disables further option processing.  Any arguments after the -- are treated as filenames and arguments.  An argument of - is equivalent to --.
1
27.01.2020, 20:50

Теги

Похожие вопросы