如何在 bash here-document 中键入选项卡?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3731513/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:38:52  来源:igfitidea点击:

How do you type a tab in a bash here-document?

bashtabsheredoc

提问by D W

The definition of a here-document is here: http://en.wikipedia.org/wiki/Here_document

这里文档的定义在这里:http: //en.wikipedia.org/wiki/Here_document

How can you type a tab in a here-document? Such as this:

如何在此处的文档中键入选项卡?比如这个:

cat > prices.txt << EOF
coffee\t.50
tea\t.50
burger\t.00
EOF

UPDATE:

更新:

Issues dealt with in this question:

本题涉及的问题:

  1. Expanding the tabcharacter
  2. While not expanding the dollar sign
  3. Embeddinga here-doc in a file such as a script
  1. 扩展制表
  2. 虽然不扩大美元符号
  3. 将 here-doc嵌入到文件(例如脚本)中

采纳答案by Paused until further notice.

You can embed your here doc in your script and assign it to a variable without using a separate file at all:

您可以在脚本中嵌入您的 here 文档并将其分配给一个变量,而无需使用单独的文件:

#!/bin/bash
read -r -d '' var<<"EOF"
coffee\t.50
tea\t.50
burger\t.00
EOF

Then printfor echo -ewill expand the \tcharacters into tabs. You can output it to a file:

然后printforecho -e\t字符扩展为制表符。您可以将其输出到文件:

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

Or assign the variable's value to itself using printf -v:

或者使用以下命令将变量的值分配给自身printf -v

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

Now varor the file prices.txtcontains actual tabs instead of \t.

现在var或文件prices.txt包含实际选项卡而不是\t.

You could process your here doc as it's read instead of storing it in a variable or writing it to a file:

您可以在读取此处的文档时对其进行处理,而不是将其存储在变量中或将其写入文件:

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 .50    # I'm using spaces between fields in this case
    tea .50
    burger .00
    EOF

Note that I used <<-for the here doc operator in this case. This allows me to indent the lines of the here doc for readability. The indentation mustconsist of tabs only (no spaces).

请注意,<<-在这种情况下,我使用了 here doc 运算符。这使我可以缩进此处文档的行以提高可读性。缩进必须仅包含制表符(无空格)。

回答by chuck

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

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

回答by martin clayton

For me, I type ctrl-V followed by ctrl-I to insert a tab in the bash shell. This gets around the shell intercepting the tab, which otherwise has a 'special' meaning. Ctrl-V followed by a tab should work too.

对我来说,我键入 ctrl-V 后跟 ctrl-I 以在 bash shell 中插入一个选项卡。这绕过了拦截选项卡的外壳,否则它具有“特殊”含义。Ctrl-V 后跟一个选项卡也应该起作用。

When embedding dollar signs in a here document you need to disable interpolation of shell variables, or else prefix each one with a backslash to escape (i.e. \$).

当在 here 文档中嵌入美元符号时,您需要禁用 shell 变量的插值,或者在每个变量前面加上一个反斜杠以进行转义(即\$)。

Using your example text I ended up with this content in prices.txt:

使用您的示例文本,我最终在 price.txt 中得到了以下内容:

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

because $1and $5are not set. Interpolation can be switched off by quoting the terminator, for example:

因为$1$5没有设置。可以通过引用终止符来关闭插值,例如:

cat > prices.txt <<"EOF"

回答by par

As others have said, you can type CTRL-V then tab to insert a single tab when typing.

正如其他人所说,您可以键入 CTRL-V 然后按 Tab 键在键入时插入单个选项卡。

You can also disable bash tab-completion temporarily, for example if you want to paste text or if you want to type a long here-doc with lots of tabs:

您还可以暂时禁用 bash 选项卡完成功能,例如,如果您想粘贴文本或者如果您想输入一个包含许多选项卡的长 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

EDIT: If you're on a Mac and use iTerm 2, there is now a "Paste with literal tabs" option that allows pasting code with tabs onto the bash command line.

编辑:如果您在 Mac 上使用iTerm 2,现在有一个“用文字标签粘贴”选项,允许将带有标签的代码粘贴到 bash 命令行上。

回答by Daniel Patru

Here's a shorter version of Dennis Williamson'sanswer. Inspiration from here: http://tldp.org/LDP/abs/html/here-docs.html.

这是丹尼斯威廉姆森回答的简短版本。灵感来自这里:http: //tldp.org/LDP/abs/html/here-docs.html

#!/bin/bash

var=$(echo -e "$(cat <<"EOF"
coffee\t.50
tea\t.50
burger\t.00
EOF
)")

echo "$var"

回答by tripleee

I note that the correct answer has already been given, but I am attempting to summarize into a more succinct answer.

我注意到已经给出了正确的答案,但我试图总结成一个更简洁的答案。

1.There is nothing to prevent you from having literal tab characters in a here document.

1.没有什么可以阻止您在此处的文档中使用文字制表符。

To type a literal tab at the Bash prompt, you need to escape it. The escape character is ctrl-V (unless you have custom bindings to override this).

要在 Bash 提示符下键入文字选项卡,您需要对其进行转义。转义字符是 ctrl-V(除非您有自定义绑定来覆盖它)。

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

In most any programmer's editor, it should be trivial to insert a literal tab character (although some editors might want escaping, too. In Emacs, ctrl-Q TAB inserts a literal tab).

在大多数程序员的编辑器中,插入文字制表符应该是微不足道的(尽管有些编辑器也可能想要转义。在 Emacs 中,ctrl-Q TAB 插入文字制表符)。

For legibility, it might be better to use some sort of escape instead of a literal tab character. In Bash, the $'...' string syntax is convenient for this.

为了易读性,最好使用某种转义符而不是文字制表符。在 Bash 中, $'...' 字符串语法对此很方便。

2.To prevent variable expansion, quote all dollar signs, or put the here doc terminator in quotes.

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

In this context, it doesn't matter whether you use single or double quotes.

在这种情况下,使用单引号还是双引号都没有关系。

3.I am not sure I understand this subquestion. The purpose of a here document is to embed it in a script. The previous example illustrates how to pass a here document to hexdump in a script, or at the command line.

3.我不确定我是否理解这个子问题。here 文档的目的是将其嵌入到脚本中。前面的示例说明了如何在脚本中或在命令行中将 here 文档传递给 hexdump。

If you want to use the same here document multiple times, there is no straightforward way to do that directly. The script could write a here document to a temporary file, then pass that temporary file to multiple commands, then erase the temporary file. (Take care to use trapto remove the temporary file also in case the script is interrupted.)

如果您想多次使用同一个 here 文档,没有直接的方法可以直接做到这一点。该脚本可以将此处的文档写入临时文件,然后将该临时文件传递给多个命令,然后擦除该临时文件。(注意使用trap删除临时文件,以防脚本中断。)

You could also put the contents of the here document in a variable, and interpolate that.

您还可以将 here 文档的内容放在一个变量中,并对其进行插值。

# Note embedded newlines inside the single quotes,
# and the use of $'...\t...' to encode tabs
data=$'coffee\t.50
tea\t.50
burger\t.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

You could equivalently use echo -E "$data" | wc; echo -E "$data" | grep -c $'\t'but using echo is not very elegant and might be less portable (though if your target is bash, all echos should be the same. If your target is Bourne shell in general, you might also spend an external process for each echo).

您可以等效地使用echo -E "$data" | wc; echo -E "$data" | grep -c $'\t'但使用 echo 不是很优雅,并且可能不太便携(尽管如果您的目标是 bash,则所有回声应该是相同的。如果您的目标通常是 Bourne shell,您还可能为每个回声花费一个外部进程)。

回答by chrissm

Re: subquestion #3, I read this question as:

回复:子问题#3,我把这个问题读为:

"[W]hat if I wanted to[...] store the here-doc commented in the same file as the script for later reference?"

“[W] 如果我想[...] 将注释的 here-doc 存储在与脚本相同的文件中以供以后参考怎么办?

Use the script name as the output of the here doc, appending rather than replacing, assuming the executor also has write permissions. Shell comments are not interpreted during a here doc block.

使用脚本名称作为 here doc 的输出,附加而不是替换,假设执行者也有写权限。Shell 注释在 here doc 块期间不被解释。

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

In a similar way you can use a here doc to write out a new script expanding variables to values, exec it, and then you have an exact record of what was run rather having to trace the code.

以类似的方式,您可以使用 here doc 写出一个将变量扩展为值的新脚本,执行它,然后您就可以准确记录运行的内容,而不必跟踪代码。

回答by javabrett

Tabs that are pasted into a heredoc vanish, because bashis still interpreting them as special characters marking the start of an auto-completion sequence/request.

粘贴到 heredoc 中的选项卡消失了,因为bash仍在将它们解释为标记自动完成序列/请求开始的特殊字符。

If you want to quickly paste a heredoc in the current shell, you can do this by disabling auto-completion for the life of the current shell.

如果你想在当前 shell 中快速粘贴一个 heredoc,你可以通过在当前 shell 的生命周期内禁用自动完成来做到这一点。

Here's what happens with normal auto-completion if you paste a heredoc containing tabs:

如果您粘贴包含标签的 heredoc,以下是正常自动完成会发生的情况:

$ cat <<EOF
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> EOF
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE

Run this command:

运行此命令:

bind "set disable-completion on"

bind "set disable-completion on"

Paste again and your tabs are retained:

再次粘贴并保留您的选项卡:

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

回答by peak

One simple and direct solution to the original problem is to use the $(echo $'...')idiom:

原始问题的一种简单而直接的解决方案是使用$(echo $'...')习语:

sed 's/\t/\t/g' > prices.txt << 'EOF'
coffee\t.50
tea\t.50
burger\t.00
EOF

回答by Walker Hale IV

If you use a tool like sed and quote the delimiter (EOF), things can get simpler:

如果您使用像 sed 这样的工具并引用分隔符 (EOF),事情会变得更简单:

##代码##
  • Quoting EOF prevents parameter (dollar sign) expansion.
  • sed converts '\t' into tab characters.
  • If you have patters like \\tin your here doc, then you would need a more complex sed invocation such as: sed -e 's/\\t/\t/g' -e 's/\\\t/\\t/g'.
  • 引用 EOF 可防止参数(美元符号)扩展。
  • sed 将 '\t' 转换为制表符。
  • 如果你有一个像patters\\t在你这里的文档,那么你就需要一个更复杂的sed调用,例如:sed -e 's/\\t/\t/g' -e 's/\\\t/\\t/g'