Простой скрипт не работает

Я пытаюсь написать простой скрипт, в котором, если в строке 7 запятых, будет возвращено либо true, либо false. Но я столкнулся с парой ошибок. Первая ошибка исходит от grep, если я уберу -o, я все равно получу ошибку. И я не уверен, почему отображается 0 и почему он возвращается как false? У меня также проблемы с равным; так как ни -eq, ни == не работают.

Скрипт:

#!/bin/bash
str="a,g,5,d,s,c,f,s"
stat=grep -o "," <<< "$str" | wc -l
if [ $stat == '7' ];then
        echo "true"
else
        echo "false"
fi

Вот результат, который я получаю:

./tesh.sh
./tesh.sh: line 3: -0: command not found
0
./tesh.sh: line 4: [: ==: unary operator expected
false

person BB956    schedule 17.07.2018    source источник
comment
shellcheck.net — ваш друг. Здесь много отдельных мелких ошибок, нет отдельной ошибки, чтобы сделать хороший вопрос SO.   -  person Charles Duffy    schedule 17.07.2018


Ответы (2)


Исправьте следующую строку в вашем скрипте.

stat=$(grep -o "," <<< "$str" | wc -l)

Также исправьте вас, если условие, подобное приведенному ниже, вы сравниваете с числовым значением.

if [[ $stat -eq 7 ]];then
person Abhijit Pritam Dutta    schedule 17.07.2018
comment
это только часть. [ $stat == '7' ] тоже неверно; должно быть [ "$stat" = 7 ] для надежной работы. - person Charles Duffy; 17.07.2018
comment
@CharlesDuffy ... Странно, я бы использовал [[ $stat -eq 7 ]], поскольку $stat всегда должен быть числовым. - person Andre Gelinas; 17.07.2018
comment
Цитаты по-прежнему важны. Если бы stat был пустым, [ $stat -eq 7 ] имел бы довольно бесполезную ошибку. - person Charles Duffy; 17.07.2018
comment
@CharlesDuffy, я этого не видел. Спасибо. - person Abhijit Pritam Dutta; 17.07.2018
comment
@AndreGelinas, если вы собираетесь использовать синтаксис только для bash, лучше использовать (( )), чтобы попасть в правильный числовой контекст, чтобы вы могли использовать >, <, >= и т. д. для числовых сравнений. - person Charles Duffy; 17.07.2018
comment
Это сработало для меня! Спасибо! - person BB956; 17.07.2018

Здесь несколько вопросов.

  • var=value somecommand arg1 arg2 ... экспортирует var в среду, в которой выполняется somecommand (без изменения среды для каких-либо будущих команд); он не устанавливает key на выходе somecommand.

  • [ $stat == '7' ] имеет несколько различных проблем:

    • [ doesn't guarantee that == is a supported operation at all. The POSIX test specification guarantees that = will be available for string comparisons, or -eq for numeric ones. ([[ does guarantee support for ==, and avoid the need for quotes; its use also explicitly disclaims portability to baseline /bin/sh implementations).
    • $stat, без кавычек, может расширяться до неизвестного количества слов, в зависимости от текущего значения IFS и содержимого переменной. Это означает, что если ваша команда wc по какой-то причине не удалась, вы можете в конечном итоге запустить [ = 7 ], что приводит к ошибке «неожиданный унарный оператор», а не [ "" = 7 ], что правильно неверно. Напротив, 7 не нужно заключать в кавычки — он не может расширяться ни на что, кроме самого себя.

Вместо того, чтобы подсчитывать количество запятых, считайте элементы, разделенные запятыми, в массив и подсчитайте количество элементов массива. Это можно сделать, используя только инструменты, встроенные в саму оболочку, как описано в BashFAQ #1 - - таким образом, без каких-либо (существенных) накладных расходов на запуск внешних исполняемых файлов, таких как wc или grep:

IFS=, read -r -a pieces <<<"$str"
if (( ${#pieces[@]} == 8 )); then
  echo "Correct number of pieces found"
else
  echo "Error: Only ${#pieces[@]} pieces found in line"
fi

Это позволяет обращаться к элементам по отдельности:

echo "This first piece is ${pieces[0]}"
echo "The last piece is ${pieces[7]}"
person Charles Duffy    schedule 17.07.2018