У меня было такое странное поведение этим утром в терминале bash:
user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
bash: [: missing «]»
user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
true
- Первая команда была вставлена из скрипта, отредактированного с помощью gedit.
- Второй был набран прямо в терминале.
После некоторых копаний я обнаружил, что удаление 30-го символа (пробел между client.conf и "]") и замена его пробелом снова заставили команду работать.
Мое предположение было верным: неизвестный пустой символ проскользнул в команду , но вопрос таков:
- Как я могу показать эти символы в терминале, чтобы я мог отладить команду? И более важно:
- Как я могу предотвратить это снова?
Кстати, я использую Ubuntu 18.04 / французский язык, скрипт, с которого я вставляю команду, находится на USB-накопителе и, возможно, также был отредактирован в Windows.
Спасибо за ваши очень хорошие ответы. Плохой символ - это неразрывный пробел c2 a0 UTF-8. Вопрос Как удалить специальный символ 'M-BM-' с помощью sed имеет интересный факт об этом персонаже.
Странно то, что сценарий свободен от этого персонажа. Так что я не знаю, откуда это.
источник
history 2|xxd
(потому чтоhistory
сама команда всегда является последней в списке), либо введитеhistory|grep "CommandWithProblem"|xxd
. Вы можете использовать любую другую программу шестнадцатеричного отображения вместоxxd
, но по умолчанию это формат, который мне нравится.set -x
. Это покажет вам команду и как она разделена. Это не обязательно говорит «плохой персонаж здесь», но показывает, что bash не разделяется на этого персонажа.Ответы:
Один из вариантов - посмотреть на символы, которые вы пытаетесь использовать, с помощью шестнадцатеричной программы просмотра или редактора.
hexdump
хороший вариант, если вы ограничены терминалом.Вы можете увидеть здесь , что
space
,close-square-brace
,space
являются правильными -0x20
,0x5D
,0x20
.Эти значения представляют собой коды ASCII, отображаемые в шестнадцатеричном формате . Любое значение за пределами диапазона
0x20
-0x7E
это не « печатный символ » в отношении ASCII и, скорее всего, не будет хорошо работать с интерфейсами командной строки.Примечание: я скопировал вашу первую « ломаную » строку для использования в
hexdump
приведенном выше примере, поэтому что-то заменило не-ASCII-пространство пробелом ASCII между вашим исходным источником и вашим заданным вопросом.Чтобы повторить это, выполните следующие действия:
hexdump -Cv <<"EOF"
и нажмитеEnterEOF
в отдельной строке и нажмитеEnterТерминалы и интерфейсы командной строки плохо обрабатывают специальные символы - как вы обнаружили. Если вы не очень осторожны с форматированием документов, у вас также будут проблемы с Microsoft Word (и другими), использующими " умные кавычки ", тире, список можно продолжить ...
Найдите разницу: (верхняя часть - « умные цитаты », нижняя - « прямые цитаты »)
Здесь, открытые кавычки не просто ASCII кавычки (
"
), но являются Unicode / UTF-8 серия -0xE2
,0x80
,0x9C
илиU+201C
- что терминал не будет обрабатывать как можно было бы ожидать.Предложение Киви
cat -A
также делает работу:Примечание: при использовании у
echo "..." | hd
вас есть шанс, что bash заменит части строки, которую вы пытаетесь проверить. Это особенно важно при попытке проверить компоненты скрипта.Например попробуйте:
Эти методы заменяют компоненты соответствующим текстом. Чтобы избежать этого, используйте один из следующих подходов. Обратите внимание на использование одинарных кавычек (
'
) и « heredoc в кавычках » ("EOF"
).источник
echo "[ -f /etc/openvpn.ovpn ]" | hd
возвращается[...] c2 a0 [...]
. Мы можем видеть неразрывный пробел символа c2 a0 UT-8Вы можете использовать
cat
с-A
опцией: из руководства:Так
cat -A yourscrip.sh
покажет вам невидимых и странных персонажей.источник
echo "[ -f /etc/openvpn.ovpn ]" | cat -A
возвращается[ -f /etc/openvpn/client.ovpnM-BM- ]$
. Мы можем видеть неразрывное пространство символа M-BM- UT-8echo "<your command>" | hd
должно сработать. Ищите возврат (0x08) или символы с кодами> = 80.echo "<your command>" | wc -b
и проверка того, что количество соответствует тому, что вы видите, также является хорошей идеей.Копирование файлов из файлов, созданных чем-либо с «Office» в его названии, опасно, потому что такое программное обеспечение часто позволяет себе сменить символы: на французском языке ищите двойные кавычки, замененные на «guillemets», на английском языке - простые кавычки, заменяемые их открыть / закрыть эквиваленты. Самым сложным из всех, что я нашел, был неразрывный пробел шириной 0 в середине имени файла (3 дня простоя сервера ...).
источник
hd
это сокращение,hexdump
которое также упоминается в ответе Атти.hd
эквивалентноhexdump -C
.echo "[ -f /etc/openvpn.ovpn ]" | hd
возвращается[...] c2 a0 [...]
. Мы можем видеть неразрывный пробел символа c2 a0 UT-8Bash и другие оболочки, такие как zsh, могут открывать текущую командную строку в редакторе. По умолчанию ярлыка для Баша
C-x C-e
( CtrlX CtrlE), и она открывается в первом доступны$VISUAL
,$EDITOR
и Emacs. На практике это неоценимо для отладки и изменения сложных команд. В зависимости от того, как вы на это смотрите, zsh здесь более дружелюбен, чем bash: когда редактор выходит, bash сразу же запускает команду, а zsh ждет, пока вы нажмете Enter(что даст вам больше возможностей для редактирования команды).После открытия команды в редакторе вы можете настроить свои редакторы так, чтобы они отличались от символов, отличных от ASCII.
Например, с Vim , используя эти настройки:
Или, адаптируя методы других ответов:
источник