‘]’ ожидаемая синтаксическая ошибка Bash — несмотря на то, что `]` присутствует и окружен пробелами

#bash #syntax-error #unicode-string

#bash #синтаксическая ошибка #unicode-строка

Вопрос:

При запуске моего скрипта bash у меня возникает следующая ошибка:

 ./myscript.sh:[:16: ']' expected
  

Строка 16:

     [ -d "$dir" ] amp;amp; echo "$dir" amp;amp; for file in "$dir"/*/*
  

Обычно ошибка возникает из-за пропущенного пробела в [] условии, но я не забыл об этом.
Вот остальная часть скрипта, начинающаяся со строки 14:

 for dir in "$message_directory"/*
do
    [ -d "$dir" ] amp;amp; echo "$dir" amp;amp; for file in "$dir"/*/*
    do
        if [ -d "$file" ] ; then
            if [[ -f "$file"/Message.txt || -f "$file"/Message.html ]] ; then
                hashMD5=$(md5sum "$file/message"* | cut -d " " -f1 | head -n 1)
                todelete=$(find "$directory_to_check" -type f -not -path "*$message_directory*" -name "Message*" -exec md5sum "{}" ; | grep "^$hashMD5" )
                todelete=$(echo "$todelete" | tr -s " " | cut -d " " -f2-)
                todelete=$(echo "$todelete" | sed -E 's/(Message[0-9][0-9]*). /1/' )
                if [[ ! -z "$todelete" ]] ; then
                    echo "searching for hash : $hashMD5"
                    while read -r line; do
                        message_todelete=$(echo "$line")
                        echo "I will delete : $message_todelete"
                        md5sum "$todelete/Message"* | head -n 1
                        #rm -r "$line"
                    done <<< "$todelete"
                fi
            fi

        fi
    done
done
  

Я попытался запустить скрипт dash , и он работал до тех <<< пор, пока не будет выполнено, что понятно, но никаких ошибок о пропущенных ]

Ответ №1:

Ваша ошибка связана с наличием пробелов в Юникоде (в диапазоне, отличном от ASCII) сразу после закрытия, в частности, символа Unicode ] БЕЗ ПРОБЕЛОВ (Unicode U 00A0).

Bash не распознает такие пробелы, поэтому он не может найти закрытие ] .[1]

Вы можете проверить это следующим образом:

 LC_ALL=C cat -et myscript.sh
  

отображает символы, отличные от ASCII, в виде комбинаций мета-ключей.
Пробелы без разрыва в Юникоде отображаются как M-BM- .

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


Если вам нужен автоматический перевод пробелов и знаков препинания, отличных от ASCII, в файлах, закодированных в UTF-8, в их ближайшие эквиваленты ASCII, вы можете использовать мой nws (нормализация пробелов) CLI; например:
nws --ascii -i.bak myscript.sh .
nws может быть установлен через реестр npm путем выполнения [sudo] npm install -g nws-cli или вручную из репозитория.


[1] [ и ] должны быть отделены от окружающих элементов пробелом, чтобы Bash распознал их как синтаксические элементы. В этом случае Bash увидел word ]<no-break-space> , потому что пробел без разрыва не является пробелом с точки зрения Bash, и поэтому закрытие ] не было найдено.

Комментарии:

1. Вы были правы насчет пробела в юникоде, я проверил вашу команду и удалил ее, скрипт теперь работает. Но, похоже, это было после закрытия ]

2. @user3714670: Спасибо — да, пробел без разрыва появился после ] — Я обновил свой пост.

3. @anubhava: Я просто вошел в режим редактирования и скопировал оттуда код скрипта.