here-document的定义如下: http://en.wikipedia.org/wiki/Here_document
如何在here-document中键入选项卡?比如这个:
cat > prices.txt << EOF
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF
更新:
这个问题涉及的问题:
答案 0 :(得分:19)
TAB="$(printf '\t')"
cat > prices.txt << EOF
coffee${TAB}\$1.50
tea${TAB}\$1.50
burger${TAB}\$5.00
EOF
答案 1 :(得分:15)
您可以在脚本中嵌入此文档,并将其分配给变量,而不使用单独的文件:
#!/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运算符。这允许我缩进这里doc的行以便于阅读。缩进必须仅包含制表符(无空格)。
答案 2 :(得分:8)
对我来说,我输入ctrl-V后跟ctrl-I在bash shell中插入一个标签。这绕过了拦截制表符的shell,否则它具有“特殊”含义。 Ctrl-V后跟一个标签也应该有用。
在here文档中嵌入美元符号时,需要禁用shell变量的插值,或者在每个变量前面添加反斜杠以进行转义(即\$
)。
使用您的示例文本,我在price.txt中找到了这个内容:
coffee\t.50
tea\t.50
burger\t.00
因为未设置$1
和$5
。可以通过引用终结符来关闭插值,例如:
cat > prices.txt <<"EOF"
答案 3 :(得分:5)
正如其他人所说,您可以在键入时键入CTRL-V然后选项卡以插入单个选项卡。
您也可以暂时禁用bash tab-completion,例如,如果您想要粘贴文本,或者如果要输入带有大量标签的long here-doc:
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命令行上。
答案 4 :(得分:2)
我注意到已经给出了正确的答案,但我试图总结一个更简洁的答案。
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插入一个文字制表符。)
为了易读,最好使用某种转义而不是文字制表符。在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。我不确定我理解这个问题。这里的文档的目的是将其嵌入脚本中。前面的示例说明了如何在脚本或命令行中将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 shell,你可能会也为每个回声花费一个外部过程。)
答案 5 :(得分:2)
以下是Dennis Williamson's answer的缩短版本。来自这里的灵感: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"
答案 6 :(得分:1)
Re:子问题#3,我把这个问题读成:
“如果我想[...]存储here-doc评论相同的话 file作为脚本供以后参考?“
使用脚本名称作为此文档的输出,附加而不是替换,假设执行程序也具有写入权限。在此处的doc块中不会解释Shell注释。
_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
以类似的方式,您可以使用here doc编写一个新的脚本,将变量扩展为值,执行它,然后您就可以准确记录运行的内容而不必跟踪代码。
答案 7 :(得分:1)
粘贴到heredoc中的标签消失,因为bash
仍然将它们解释为标记自动完成序列/请求开始的特殊字符。
如果要在当前shell中快速粘贴heredoc,可以通过在当前shell的生命周期内禁用自动完成来执行此操作。
如果您粘贴包含标签的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
答案 8 :(得分:0)
原始问题的一个简单直接的解决方案是使用 $(echo $'...')成语:
cat > prices.txt << EOF
$(echo $'coffee\t$1.50')
$(echo $'tea\t$1.50')
$(echo $'burger\t$5.00')
EOF
答案 9 :(得分:0)
如果您使用像sed这样的工具并引用分隔符(EOF),事情会变得更简单:
sed 's/\\t/\t/g' > prices.txt << 'EOF'
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF
\\t
这样的模式,那么你需要一个更复杂的sed调用,例如:sed -e 's/\\t/\t/g' -e 's/\\\t/\\t/g'
。答案 10 :(得分:0)
使用@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
答案 11 :(得分:0)
如果您想对文件缩进使用制表符和为heredoc: 您只需要将缩进的制表符与带有空格的文档制表符分开:
try_me() {
# @LinuxGuru's snippet; thanks!
sed 's/^ //g' >> tmp.conf <<-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
}
try_me
唯一的缺点是不缩进的行看起来有点奇怪;他们在脚本上有一个领先的空白字符
/var/log/nginx/*log
}
但是,在生成的文件中不会出现这种情况(sed 's/^ //g'
而不是 cat
)