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

313

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

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

Я понял

res=[ x] # that is [<space>x]
kalyanji
источник

Ответы:

530
echo -e ' \t '

отобразит «пробел в новой строке» ( -eозначает «включить интерпретацию обратной косой черты»):

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

Используйте 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]"

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

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

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

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

Кит Томпсон
источник
1
Мне понравился этот, он позволяет мне использовать знания printf и всех спецификаторов формата.
Арун
@JezenThomas: за него не проголосовали больше, потому что он отвечает на вопрос иначе, чем просили. В вопросе конкретно упоминается эхо, а эхо - не глагол, а команда.
Пауло Невес
@PauloNeves: я бы сказал, что он используется в качестве глагола в вопросе: «Как мне отобразить один или несколько символов табуляции, используя скрипт bash?»
Кит Томпсон
34

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

echo "[$res]"
kmkaplan
источник
1
то же самое здесь - это то, что я попробовал первым -э все работало нормально
froderik
2
@kmkaplan работает для меня в Zsh - не работает для меня в Bash
Кал
34

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

echo Hello$'\t'world.
jbatista
источник
4
+1 для более общего решения. Я использую bash годами и только сейчас узнал об этом!
Арье Лейб Таурог
Это гораздо более общий вопрос, чем принятый ответ, поскольку его можно использовать без эха.
января
22

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

echo -e "\t\t x"
Обучение
источник
16

Со страницы руководства bash:

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

Так что вы можете сделать это:

echo $'hello\tworld'
esoriano
источник
Почему это работает на cli, а не в bash-скрипте?
Freek
13

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

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

Что-то вроде следующих работ:

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

Документы Bash ( см. "Цитируемое")

quoted-insert (Cq, Cv) Добавьте следующий набранный вами символ в строку. Это как вставить последовательности клавиш, например, Cq.

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

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

-

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

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

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

богатый ремер
источник
1
Хотел бы я дать вам больше голосов за это. Я не хотел использовать -e в моих аргументах в этом случае, и это прекрасно работает. Спасибо!
Аарон Р.
"... большинство редакторов Unix"? Попытался ввести это как с vi, так и с emacs, но это также не дало желаемых результатов.
GreenMatt
Это так круто! И спас мой день при попытке использовать grepдля ловли строки, содержащие tabсимволы.
Жоэль
11

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

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

анонимное
источник
Круто, мне нравятся "BashPitfalls", отличный кусок материала, и он избавляет меня от боли в моей повседневной работе!
Джерри Тян
+1 потому что это тааак правда. Но обратите внимание, что строка kalyanji начинается с «[» и не содержит «\».
kmkaplan
2

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

# sh -e myscript.sh

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

# chmod +x myscript.sh
# ./myscript.sh
ATC
источник