Как вы вводите вкладку в документ Bash здесь? - PullRequest
24 голосов
/ 17 сентября 2010

Определение здесь-документа здесь: http://en.wikipedia.org/wiki/Here_document

Как вы можете ввести вкладку в здесь документ? Такие как это:

cat > prices.txt << EOF
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF

UPDATE:

Проблемы, затронутые в этом вопросе:

  1. Расширение вкладки Символ
  2. Не расширяя знак доллара
  3. Встраивание документа в файл, такой как скрипт

Ответы [ 11 ]

19 голосов
/ 17 сентября 2010
TAB="$(printf '\t')"

cat > prices.txt << EOF
coffee${TAB}\$1.50
tea${TAB}\$1.50
burger${TAB}\$5.00
EOF
15 голосов
/ 17 сентября 2010

Вы можете встроить свой документ Here в свой скрипт и назначить его переменной без использования отдельного файла:

#!/bin/bash
read -r -d '' var<<"EOF"
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF

Затем printf или echo -e развернут символы \t во вкладки. Вы можете вывести его в файл:

printf "%s\n" "$var" > prices.txt

Или присвоить значение переменной себе, используя printf -v:

printf -v var "%s\n" "$var"

Теперь var или файл prices.txt содержит действительные вкладки вместо \t.

Вы можете обработать документ здесь, как он читается, вместо того, чтобы хранить его в переменной или записывать в файл:

while read -r item price
do
    printf "The price of %s is %s.\n" $item $price    # as a sentence
    printf "%s\t%s\n" $item $price                  # as a tab-delimited line
done <<- "EOF"
    coffee $1.50    # I'm using spaces between fields in this case
    tea $1.50
    burger $5.00
    EOF

Обратите внимание, что в этом случае я использовал <<- для оператора здесь doc. Это позволяет мне выравнивать строки документа здесь для удобства чтения. Отступ должен состоять только из табуляций (без пробелов).

8 голосов
/ 17 сентября 2010

Для меня я набираю ctrl-V, а затем ctrl-I, чтобы вставить вкладку в оболочку bash.Это обходит оболочку, перехватывающую вкладку, которая в противном случае имеет «особое» значение.Ctrl-V, за которым следует вкладка, также должен работать.

При встраивании знаков доллара в документ здесь необходимо отключить интерполяцию переменных оболочки или префикс каждой из них с обратной косой чертой (т.е. \$).

Используя ваш пример текста, я получил это содержимое в ценах.txt:

coffee\t.50
tea\t.50
burger\t.00

, поскольку $1 и $5 не заданы.Интерполяцию можно отключить, заключив в кавычки терминатор, например:

cat > prices.txt <<"EOF"
5 голосов
/ 20 марта 2014

Как уже говорили другие, вы можете набрать CTRL-V, затем tab, чтобы вставить одну вкладку при наборе.

Вы также можете временно отключить завершение вкладок bash, например, если вы хотите вставить текст или если вы хотите ввести длинный документ с большим количеством вкладок:

bind '\C-i:self-insert'     # disable tab-completion

# paste some text or type your here-doc
# note you don't use "\t" you just press tab

bind '\C-i:complete'        # reenable tab-completion

РЕДАКТИРОВАТЬ: если вы используете Mac и используете iTerm 2 , теперь есть опция «Вставить с буквенными вкладками», которая позволяет вставлять код с вкладками в командную строку bash.

2 голосов
/ 10 мая 2013

Вот более короткая версия ответа Денниса Уильямсона . Вдохновение отсюда: http://tldp.org/LDP/abs/html/here-docs.html.

#!/bin/bash

var=$(echo -e "$(cat <<"EOF"
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF
)")

echo "$var"
2 голосов
/ 04 августа 2011

Я отмечаю, что правильный ответ уже был дан, но я пытаюсь обобщить в более краткий ответ.

1. Ничто не мешает вам иметь буквенную вкладкусимволы в документе here.

Чтобы ввести буквенную вкладку в командной строке Bash, вам необходимо ее избежать.Экранирующим символом является ctrl-V (если у вас нет пользовательских привязок для переопределения этого).

$ echo -n 't<ctrl-v><tab>ab' | hexdump -C
00000000  74 09 61 62                                       |t.ab|
00000004

В большинстве редакторов любого программиста вставка литерального символа табуляции должна быть тривиальной (хотя некоторые редакторы могут захотеть экранироватьКроме того, в Emacs ctrl-Q TAB вставляет буквенную вкладку).

Для удобочитаемости, возможно, было бы лучше использовать какой-либо вид экранирования вместо буквального символа табуляции.В Bash для этого удобен строковый синтаксис $ '...'.

2. Чтобы предотвратить расширение переменной, заключите все знаки доллара в кавычки или поставьте терминатор here doc в кавычках.

$ hexdump -C <<HERE
> t<ctrl-v><tab>\$ab
HERE
00000000  74 09 24 61 62 0a                                 |t.$ab.|
00000006

$ hexdump -C <<'HERE'
> t<ctrl-v><tab>$ab
HERE
00000000  74 09 24 61 62 0a                                 |t.$ab.|
00000006

В этом контексте не имеет значения, используете ли вы одинарные или двойные кавычки.

3. Я не уверен, что понимаю этот подвопрос.Цель этого документа - встроить его в скрипт.В предыдущем примере показано, как передать документ here в hexdump в сценарии или в командной строке.

Если вы хотите использовать один и тот же документ здесь несколько раз, простого способа сделать это напрямую не существует.Сценарий может записать здесь документ во временный файл, затем передать этот временный файл нескольким командам, а затем стереть временный файл.(Используйте trap для удаления временного файла также в случае, если сценарий прерван.)

Вы также можете поместить содержимое документа here в переменную и интерполировать его.

# Note embedded newlines inside the single quotes,
# and the use of $'...\t...' to encode tabs
data=$'coffee\t$1.50
tea\t$1.50
burger\t$5.00'

# Run Word Count on the data using a here document
wc <<HERE
$data
HERE

# Count number of tab characters using another here document with the same data
grep -c $'\t' <<HERE
$data
HERE

Вы могли бы эквивалентно использовать echo -E "$data" | wc; echo -E "$data" | grep -c $'\t', но использование echo не очень элегантно и может быть менее переносимым (хотя, если ваша цель bash, все эхо должны быть одинаковыми. Если ваша цель - оболочка Bourne в целом, вы можететакже провести внешний процесс для каждого эха).

1 голос
/ 15 мая 2017

Вкладки, вставленные в heredoc, исчезают, поскольку bash по-прежнему интерпретирует их как специальные символы, отмечающие начало последовательности / запроса автозаполнения.

Если вы хотите быстро вставить heredoc вВ текущей оболочке это можно сделать, отключив автозаполнение на весь срок службы текущей оболочки.

Вот что происходит с обычным автозаполнением, если вы вставляете heredoc, содержащий вкладки:

$ cat <<EOF
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
EOF
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE

Запустите эту команду:

bind "set disable-completion on"

Вставьте снова и ваши вкладки сохранятся:

$ cat <<EOF
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> EOF
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
1 голос
/ 10 января 2012

Re: подзапрос # 3, я читаю этот вопрос как:

"[W], если я хочу [...] сохранить комментарий здесь в том же файле, что исценарий для дальнейшего использования? "

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

_thisline=${LINENO}
cat <<EOF >>$0
#====== $(date) =========
#On this run, these variable values were used as of line ${_thisline}: A=${A}, B=${B}, B=${C}

EOF

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

0 голосов
/ 14 сентября 2018

Используйте @EOF, и он сохранит вкладки.

cat >> /etc/logrotate.d/nginx <<@EOF
/var/log/nginx/*log { 
    daily
    rotate 10
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
        /bin/kill -USR1 $(cat /var/run/nginx.pid 2>/dev/null) 2>/dev/null || :
    endscript
}
@EOF
0 голосов
/ 29 октября 2014

Если вы используете такой инструмент, как sed и заключаете в кавычки разделитель (EOF), все может стать проще:

sed 's/\\t/\t/g' > prices.txt << 'EOF'
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF
  • Кавычка EOF предотвращает расширение параметра (знак доллара).
  • sed преобразует '\ t' в символы табуляции.
  • Если в вашем документе здесь есть шаблоны типа \\t, вам потребуется более сложный вызов sed, такой как: sed -e 's/\\t/\t/g' -e 's/\\\t/\\t/g'.
...