[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: почему глючит ls



On 2016-01-23, dimas wrote:

> да уж, прикол... а кто-нибудь может объяснить, почему в случае с touch "-l"
> аргумент в кавычках все равно парсится как ключ?

Откройте POSIX:

  http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
     2. Shell Command Language

  The shell operates according to the following general overview of
  operations. The specific details are included in the cited sections of this
  chapter.

      The shell reads its input from a file (see sh), from the -c option or
      from the system() and popen() functions defined in the System Interfaces
      volume of IEEE Std 1003.1-2001. If the first line of a file of shell
      commands starts with the characters "#!", the results are unspecified.

      The shell breaks the input into tokens: words and operators; see Token
      Recognition.

      The shell parses the input into simple commands (see Simple Commands)
      and compound commands (see Compound Commands).

      The shell performs various expansions (separately) on different parts of
      each command, resulting in a list of pathnames and fields to be treated
      as a command and arguments; see Word Expansions.

      The shell performs redirection (see Redirection) and removes redirection
      operators and their operands from the parameter list.

      The shell executes a function (see Function Definition Command),
      built-in (see Special Built-In Utilities), executable file, or script,
      giving the names of the arguments as positional parameters numbered 1 to
      n, and the name of the command (or in the case of a function within a
      script, the name of the script) as the positional parameter numbered 0
      (see Command Search and Execution).

      The shell optionally waits for the command to complete and collects the
      exit status (see Exit Status for Commands).

Т.е. при разборе строки происходит несколько шагов. С ``touch "-l"`` мы на шаге:


      The shell breaks the input into tokens: words and operators; see Token
      Recognition.

Смотрим по ссылке:

  2.3 Token Recognition

    If the current character is backslash, single-quote, or double-quote (
    '\', '", or ' )' and it is not quoted, it shall affect quoting for
    subsequent characters up to the end of the quoted text. The rules for
    quoting are as described in Quoting. During token recognition no
    substitutions shall be actually performed, and the result token shall
    contain exactly the characters that appear in the input (except for
    <newline> joining), unmodified, including any embedded or enclosing quotes
    or substitution operators, between the quote mark and the end of the
    quoted text. The token shall not be delimited by the end of the quoted
    field.

    If the current character is an unquoted <blank>, any token containing the
    previous character is delimited and the current character shall be
    discarded.

    If the previous character was part of a word, the current character shall
    be appended to that word.

Вот и обьяснение. Кавычки попадают в shell, обрабатываются и не доходят до
команды. Т.е. кавычки - это особенность shell, команда вообще ни при чем.


В разных контекстах выполняются разные шаги. Стоит раз разобраться.

Например ``Parameter Expansion`` не делается в одинарных кавычках.

Для проверки на пустоту важно взять параметер в двойные кавычки. built-in Bash
test как то отрабатывает:

  $ [ -z -a -z ]
  $ x=
  $ [ -z $x -a -z $x ]


В GNU coreutils это не срабатывает:

  bash# /usr/bin/\[ -z -a -z ]
  /usr/bin/[: extra argument ‘-z’

  bash# /usr/bin/\[ -z $x -a -z $x ]
  /usr/bin/[: extra argument ‘-z’

В FreeBSD sh также не позволяет:

  $ [ -z -a -z ]
  [: -a: unexpected operator
  $ [ -z $x -a -z $x ]
  [: -a: unexpected operator

Расширение Bash работает двояко:

  $ [[ -z ]]
  bash: unexpected argument `]]' to conditional unary operator
  bash: syntax error near `]]'

тогда как это сработает:

  bash# [[ -z $x ]]

Признаюсь что у меня нет 100% гарантии с обьяснения мануала почему оно
работает. Прямо так не сказано. bash(1):

  [[ expression ]]

         Return a status of 0 or 1 depending on the evaluation of the
         conditional expression expression. Expressions are composed of the
         primaries described below under CONDITIONAL EXPRESSIONS. Word
         splitting and pathname expansion are not performed on the words
         between the [[ and ]]; tilde expansion, parameter and variable
         expansion, arithmetic expansion, command substitution, process
         substitution, and quote removal are performed. Conditional operators
         such as -f must be unquoted to be recog‐ nized as primaries.

       See the description of the test builtin command (section SHELL BUILTIN
       COMMANDS below) for the handling of parameters (i.e. missing
       parameters).

Т.е. сделается пустая подстановка вместо $x, но место быдет считаться занятым
потому что не происходит Word splitting?

Переносимый синтаксис:

  $ [ -z "$x" -a -z "$x" ]

Еще пример Bash расширения когда от контекста зависит какие шаги выбираются по
преобразованию строки:

  $ [[ axa == *x* ]] && echo ok

Вспоминаем что в ``[[`` не делается pathname expansion и дополнительно:

  When the == and != operators are used, the string to the right of the operator
  is considered a pattern and matched according to the rules described below
  under Pattern Matching, as if the extglob shell option were enabled.

Этим пользуюсь вместо:

  case axa in *x*) echo ok;; esac

-- 
http://defun.work/


Reply to: