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


313

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

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

Я понял

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

Ответы:


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]"

1
то же самое здесь - это то, что я попробовал первым -э все работало нормально
froderik

2
@kmkaplan работает для меня в Zsh - не работает для меня в Bash
Кал

34

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

echo Hello$'\t'world.

4
+1 для более общего решения. Я использую bash годами и только сейчас узнал об этом!
Арье Лейб Таурог

Это гораздо более общий вопрос, чем принятый ответ, поскольку его можно использовать без эха.
января


16

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

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

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

echo $'hello\tworld'

Почему это работает на 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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.