Подтвердить что ты не робот

Как ввести вкладку в bash здесь-документе?

Определение здесь-документа здесь: 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:

Вопросы, рассматриваемые в этом вопросе:

  • Расширение символа
  • Не расширяя знак доллара
  • Встраивание a-doc в файл, например script
4b9b3361

Ответ 1

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

#!/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 здесь в этом случае. Это позволяет мне отступать от строк этого документа для удобочитаемости. Отступ должен состоять только из вкладок (без пробелов).

Ответ 2

TAB="$(printf '\t')"

cat > prices.txt << EOF
coffee${TAB}\$1.50
tea${TAB}\$1.50
burger${TAB}\$5.00
EOF

Ответ 3

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

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

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

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

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

cat > prices.txt <<"EOF"

Ответ 4

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

Вы также можете временно отключить закрытие вкладки 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

EDIT: если вы на Mac и используете iTerm 2, теперь есть опция "Вставить с буквальными вкладками", которая позволяет вставлять код с вкладками в командной строке bash.

Ответ 5

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

1. Нет ничего, что помешало бы вам иметь буквальные символы табуляции в документе здесь.

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

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

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

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

2. Чтобы предотвратить расширение переменной, укажите все знаки доллара или поставьте здесь терминатор 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. Я не уверен, что понимаю это подзапрос. Цель этого документа - встроить его в script. В предыдущем примере показано, как передать документ здесь в hexdump в script или в командной строке.

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

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

# 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', но использовать эхо не очень элегантно и, возможно, менее портативно (хотя, если ваша цель Bash, все эхо-сигналы должны быть одинаковыми. Если ваша цель - оболочка Bourne в целом, вы можете также тратите внешний процесс для каждого эха).

Ответ 6

Re: subquestion # 3, я прочитал этот вопрос как:

"[W], если я захочу [...] сохранить здесь-doc в одном и том же файл как script для последующей ссылки?"

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

_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

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

Ответ 7

Вот более короткая версия . Вдохновение отсюда: 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"

Ответ 8

Вкладки, вставленные в 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

Ответ 9

Одним простым и прямым решением исходной задачи является использование идиомы $(echo $'...'):

cat > prices.txt << EOF
$(echo $'coffee\t$1.50')
$(echo $'tea\t$1.50')
$(echo $'burger\t$5.00')
EOF

Ответ 10

Если вы используете такой инструмент, как 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'.