Как ввести вкладку в 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
Ответы
Ответ 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'
.