Почему арифметическое расширение работает в Bash, но не в Zsh?

Использование AWK:

awk '/'$FROM'/,/'$TO'/ {print $0}' log.txt | grep ERROR

Использование sed:

sed -n '/'$FROM'/,/'$TO'/p' log.txt | grep ERROR
4
14.01.2020, 00:02
2 ответа

Таблица tl;dr

(Y=верно, -=ложно, ¤=неудачно)(правильный тест должен бытьY -):

                     | dash  ksh   bash  zsh   
  test a  =  "$b"    | Y -   Y -   Y -   Y -    
     [ a  =  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a  =  "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a  == "$b"    | ¤ ¤   Y -   Y -   - -    
     [ a  == "$b" ]  | ¤ ¤   Y -   Y -   - -    
    [[ a  == "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a \=  "$b"    | Y -   Y -   Y -   Y -    
     [ a \=  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a \=  "$b" ]] | ¤ ¤   Y -   - -   - -    
  test a \== "$b"    | ¤ ¤   Y -   Y -   Y -    
     [ a \== "$b" ]  | ¤ ¤   Y -   Y -   Y -    
    [[ a \== "$b" ]] | ¤ ¤   Y -   - -   - -

Этот вопрос имеет два аспекта.

1 -A ==следует использовать внутри [[…]], а не в более простых […]или test.

2 -В некоторых случаях в zsh==необходимо заключать в кавычки, так как начальный = является особым и активирует расширение =cmd.


Условное выражение может быть записано внутри test …, […]или [[…]]. Но только внутри [[…]]обработка особенная и поэтому ==не вызывает проблем.

Существует несколько возможных (строковых )тестов на равенство:

'test a  =  "$b"   '
'   [ a  =  "$b" ] '
'  [[ a  =  "$b" ]]'

'test a  == "$b"   '
'   [ a  == "$b" ] '
'  [[ a  == "$b" ]]'

'test a \=  "$b"   '
'   [ a \=  "$b" ] '
'  [[ a \=  "$b" ]]'

'test a \== "$b"   '
'   [ a \== "$b" ] '
'  [[ a \== "$b" ]]'

И это можно проверить в нескольких оболочках (, то есть :dash ksh bash zsh ).

Если b=aтесты должны быть верными (, обозначенными Y),
и если b=bтесты должны быть ложными (, обозначенными -),
сбой (все, кроме кода выхода 0 или 1 ), обозначается ¤.

Во всех оболочках сверху работают только первые два.

                     | dash  ksh   bash  zsh   
  test a  =  "$b"    | Y -   Y -   Y -   Y -    
     [ a  =  "$b" ]  | Y -   Y -   Y -   Y -  

И есть четыре альтернативы (частичный список ), которые терпят неудачу в некоторой оболочке:

                     | dash  ksh   bash  zsh   
  test a  == "$b"    | ¤ ¤   Y -   Y -   - -    
     [ a  == "$b" ]  | ¤ ¤   Y -   Y -   - -    
    [[ a \=  "$b" ]] | ¤ ¤   Y -   - -   - -    
    [[ a \== "$b" ]] | ¤ ¤   Y -   - -   - - 

Вdash(устаревших оболочках )тесты терпят неудачу, потому что оболочки не распознают [[, ==или цитируемый \==в каждом случае.

Оба ==без кавычек не работают в zsh (, а не внутри [[…]]), потому что они рассматриваются (и расширяются )как обычный аргумент, а аргументы, начинающиеся с =, имеют особое значение в zsh (=cmd. ] заменяется на путь кcmd).

$ zsh -c 'test "a" == "a"'
zsh:1: = not found

$ zsh -c '[ "a" == "a" ]'
zsh:1: = not found

Двойник в кавычках=(\==)не работает как в zsh, так и в bash:

$ zsh -c '[[ "a" \== "a" ]]'
zsh:1: condition expected: \==

$ $ bash -c '[[ "a" \== "a" ]]'
bash: -c: line 0: conditional binary operator expected
bash: -c: line 0: syntax error near `\=='
bash: -c: line 0: `[[ "a" \== "a" ]]'

Итак, итоговая таблица (Y=истина, -=ложь, ¤=неудача )есть:

                     | dash  ksh   bash  zsh   
  test a  =  "$b"    | Y -   Y -   Y -   Y -    
     [ a  =  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a  =  "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a  == "$b"    | ¤ ¤   Y -   Y -   - -    
     [ a  == "$b" ]  | ¤ ¤   Y -   Y -   - -    
    [[ a  == "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a \=  "$b"    | Y -   Y -   Y -   Y -    
     [ a \=  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a \=  "$b" ]] | ¤ ¤   Y -   - -   - -    
  test a \== "$b"    | ¤ ¤   Y -   Y -   Y -    
     [ a \== "$b" ]  | ¤ ¤   Y -   Y -   Y -    
    [[ a \== "$b" ]] | ¤ ¤   Y -   - -   - -

Кроме того, Как я сказал в этом комментарии

Поскольку то, что вы выполняете, является арифметическим выражением:

[ $(( $RANDOM % 6 )) == 0 ]
  1. Поскольку IFS может иметь числа, арифметическое расширение должно быть заключено в кавычки:

    [ "$(( $RANDOM % 6 ))" == 0 ]
    
  2. Внутри арифметического выражения $ перед именем переменной не нужен.

    [ "$(( RANDOM % 6 ))" == 0 ]
    
  3. Эквивалентным арифметическим выражением (в ksh, bash, zsh )является:

    (( RANDOM % 6 == 0 ))
    

    Это позволяет избежать кавычек и условного выражения, поскольку оно устанавливает код выхода напрямую.

    4 -И, поскольку в C результатом арифметического выражения является допустимый истинный или ложный результат, который (если 0 )будет генерировать код выхода 1 (0 в противном случае ). Затем:

    (( RANDOM%6 )) && echo Click || echo Boom
    

должно быть много.

Учтите, что приоритет операторов в арифметике zsh отличается от приоритета большинства других оболочек. Найдите C _PRECEDENCES в руководстве для расширенного описания. Зедшизм.

-1
27.01.2020, 20:48

Попробуйте выполнить unsetopt equalsи повторите попытку. Или поставьте кавычки на первый символ равенства.

Если вы используете [для условий, все аргументы оцениваются нормально, а = в начале слова является полезным сокращением zsh для получения местоположения команды. например. =lsрасширяется до /bin/ls. Данный ==zsh ищет команду =и не находит ее.

Zsh в режиме posix (эмуляция sh )будет намного более совместима с bash. Многие вещи совместимы, и большинство изученных знаний о bash по-прежнему полезны, но есть определенные вещи, о которых следует знать, если вы хотите писать переносимые сценарии.

В отличие от [, который является встроенным, [[является зарезервированным словом, понятным синтаксическому анализатору, и у вас будет меньше проблем. Однако в этом случае вы используете арифметический режим, поэтому вы упрощаете его :

.
    (( RANDOM % 6 == 0 )) && echo "Boom" || echo "Click"

На самом деле сравнение с нулем даже излишне, потому что статус возврата по умолчанию отражает, равно ли значение нулю, хотя смысл обратный:

    (( RANDOM % 6 )) && echo "Click" || echo "Boom"
10
27.01.2020, 20:48

Теги

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