Эхо-символы табуляции в сценарии bash

Как отобразить один или несколько символов табуляции с помощью сценария bash? Когда я запускаю этот код

res='       'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

Я понял это

res=[ x] # that is [<space>x]

person kalyanji    schedule 08.02.2009    source источник


Ответы (9)


echo -e ' \t '

будет эхо 'пробел табуляции пробел новой строки' (-e означает 'разрешить интерпретацию экранирования обратной косой черты'):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|
person Johannes Weiss    schedule 08.02.2009
comment
Спасибо, Йоханнес. Вы помогли мне найти это решение: res = '\ t \ t'x; echo -e '[' $ res ']' - person kalyanji; 08.02.2009
comment
Вы случайно не знаете, почему echo -e не работает из Makefiles? - person dma_k; 17.10.2010
comment
Это потому, что echo -e не является POSIX и make вызывает /bin/sh, который обычно не используется программой в интерактивном режиме и обычно не -e реализован. Для переносимости используйте вместо этого printf '\t'. - person Jo So; 05.10.2012
comment
В Darwin (macOS) на странице man для команды echo не упоминается параметр -e. Однако этот вариант приемлем. - person ePi272314; 28.06.2019

Используйте printf, а не echo.

Существует несколько разных версий команды echo. Есть /bin/echo (который может быть или не быть версией GNU Coreutils, в зависимости от системы), а команда echo встроена в большинство оболочек. В разных версиях есть разные способы (или нет) для указания или отключения экранирования для управляющих символов.

printf, с другой стороны, имеет гораздо меньше вариаций. Он может существовать как команда, обычно /bin/printf, и он встроен в некоторые оболочки (bash и zsh имеют, tcsh и ksh нет), но различные версии намного более похожи друг на друга, чем разные версии echo. И вам не нужно запоминать параметры командной строки (за некоторыми исключениями; GNU Coreutils printf принимает --version и --help, а встроенный bash printf принимает -v var для сохранения вывода в переменной).

Для вашего примера:

res='           'x # res = "\t\tx"
printf '%s\n' "[$res]"

И теперь мне пора признать, что echo будет работать так же хорошо для примера, о котором вы спрашиваете; вам просто нужно заключить аргумент в двойные кавычки:

echo "[$res]"

как писал кмкаплан (два с половиной года назад я только что заметил!). Проблема с вашими исходными командами:

res='           'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

не с echo; дело в том, что оболочка заменила табуляцию пробелом до того, как echo это увидела.

echo подходит для простого вывода, например echo hello world, но вы должны использовать printf, когда хотите сделать что-то более сложное. Вы можете заставить echo работать, но результирующий код, скорее всего, выйдет из строя, если вы запустите его с другой echo реализацией или другой оболочкой.

person Keith Thompson    schedule 17.11.2011
comment
Мне понравился этот, он позволяет мне использовать знание printf и всех спецификаторов формата. - person Arun; 19.03.2013
comment
@JezenThomas: За него проголосовали не больше, потому что он отвечает на вопрос иначе, чем запрошено. В вопросе конкретно упоминается эхо, а эхо - это не глагол, а команда. - person Paulo Neves; 04.05.2017
comment
@PauloNeves: Я бы сказал, что он используется как глагол в вопросе: как мне вывести один или несколько символов табуляции с помощью сценария bash? - person Keith Thompson; 04.05.2017

Вы также можете попробовать:

echo Hello$'\t'world.
person jbatista    schedule 10.12.2009
comment
+1 для более общего решения. Я использую bash много лет и только сейчас научился этому! - person Aryeh Leib Taurog; 15.05.2012
comment
Это гораздо более общий, чем принятый ответ, поскольку его можно использовать без эха. - person jwan; 15.02.2018
comment
Кажется, это тоже работает: $'Hello\tWorld' - person Inductiveload; 11.04.2021

Поместите строку между двойными кавычками:

echo "[$res]"
person kmkaplan    schedule 08.02.2009
comment
То же самое и здесь - это то, что я попробовал в первую очередь. -е работал нормально - person froderik; 05.08.2015
comment
@kmkaplan У меня работает в zsh - не работает в bash - person Kal; 18.08.2015

вам нужно использовать флаг -e для эха, тогда вы можете

echo -e "\t\t x"
person Learning    schedule 08.02.2009

На странице руководства bash:

Особо обрабатываются слова вида $ 'строка'. Слово расширяется до строки с замененными символами, экранированными обратной косой чертой, в соответствии со стандартом ANSI C.

Итак, вы можете сделать это:

echo $'hello\tworld'
person esoriano    schedule 02.12.2015
comment
Почему это работает на cli, но не в сценарии bash? - person Freek; 28.02.2019
comment
@Freek У меня работает - может, выложите свой скрипт там, где он не работает, как отдельный вопрос? - person David Moles; 17.12.2020

Используйте дословное нажатие клавиши ^V (CTRL+V, C-v, без разницы).

Когда вы вводите ^V в терминал (или в большинстве редакторов Unix), следующий символ берется дословно. Вы можете использовать это для ввода буквального символа табуляции внутри строки, которую вы повторяете.

Примерно так работает:

echo "^V<tab>"     # CTRL+V, TAB

документы Bash (qv, " цитируемый-вставить ")

quoted-insert (C-q, C-v) Добавить следующий вводимый вами символ в строку дословно. Вот как, например, вставлять последовательности клавиш, такие как C-q.

примечание: в соответствии с этим ALT+TAB должен делать то же самое, но мы все связали эту последовательность с переключением окон, поэтому мы не можем ее использовать

tab-insert (M-TAB) Вставить символ табуляции.

--

Примечание: вы можете использовать эту стратегию со всякими необычными персонажами. Как возврат каретки:

echo "^V^M"        # CTRL+V, CTRL+M

Это связано с тем, что возврат каретки - это ASCII 13, а M - 13-я буква алфавита, поэтому, когда вы набираете ^M, вы получаете 13-й символ ASCII. Вы можете увидеть это в действии, используя ls^M в пустом приглашении, которое вставит возврат каретки, заставляя приглашение действовать так же, как вы нажимаете возврат. Когда эти символы обычно интерпретируются, дословно дает вам буквальный символ.

person rich remer    schedule 06.05.2016
comment
Хотел бы я дать вам больше голосов за это. В этом случае я не хотел использовать -e в своих аргументах, и это отлично работает. Спасибо! - person Aaron R.; 19.02.2018
comment
... большинство редакторов Unix? Пытался ввести это как с vi, так и с emacs, и ни в одном из них не дало желаемых результатов. - person GreenMatt; 11.01.2019
comment
Это так здорово! И спас мне день, когда я пытался использовать grep для отлова строк, содержащих tab символов. - person Joël; 11.02.2019

Использование echo для вывода значений переменных - распространенная ошибка Bash. Ссылка на ссылку:

http://mywiki.wooledge.org/BashPitfalls#echo_.24foo

person Anonymous    schedule 08.02.2009
comment
Круто, мне нравятся BashPitfalls, отличный материал и облегчающий мою повседневную работу! - person Jerry Tian; 27.10.2011
comment
+1 потому что это ооочень правда. Но обратите внимание, что строка кальянджи начинается с символа «[» и не содержит символа «\». - person kmkaplan; 28.11.2012

Если вы хотите использовать echo "a\tb" в сценарии, запускайте сценарий как:

# sh -e myscript.sh

В качестве альтернативы вы можете дать myscript.sh разрешение на выполнение, а затем запустить скрипт.

# chmod +x myscript.sh
# ./myscript.sh
person ATC    schedule 16.11.2011