协慌网

登录 贡献 社区

bash 中的 “cat << EOF” 如何工作?

我需要编写脚本以将多行输入输入到程序( psql )。

经过一番谷歌搜索,我发现以下语法有效:

cat << EOF | psql ---params
BEGIN;

`pg_dump ----something`

update table .... statement ...;

END;
EOF

这样可以正确构造多行字符串(从BEGIN;END; ,包括两端),并将其作为输入传递给psql

但是我不知道它是如何 / 为什么起作用的,请解释一下吗?

我主要是指cat << EOF ,我知道>输出到文件, >>追加到文件, <从文件中读取输入。

<<到底是做什么的?

并有手册页吗?

答案

当在 Bash 中处理多行文本时, cat <<EOF将多行字符串分配给 shell 变量,文件或管道时。

Bash 中cat <<EOF语法用法的示例:

1. 将多行字符串分配给 shell 变量

$ sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)

$sql变量现在也包含换行符。您可以使用echo -e "$sql"进行验证。

2. 将多行字符串传递到 Bash 中的文件

$ cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF

现在, print.sh文件包含:

#!/bin/bash
echo $PWD
echo /home/user

3. 将多行字符串传递到 Bash 中的管道

$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF

b.txt文件包含barbaz行。将相同的输出打印到stdout

这称为heredoc格式,以将字符串提供给 stdin。有关更多详细信息,请参见https://en.wikipedia.org/wiki/Here_document#Unix_shells。


来自man bash

此处文件

这种重定向指示外壳程序从当前源读取输入,直到看到仅包含单词(无尾随空格)的行。

读取到该点的所有行,然后用作命令的标准输入。

此处文档的格式为:

<<[-]word
                  here-document
          delimiter

没有对 word执行参数扩展,命令替换,算术扩展或路径名扩展。如果对 word中的任何字符加引号,则定界符是对 word删除引号的结果,并且本文档中的行不会扩展。如果未引用word,则对本文的所有行进行参数扩展,命令替换和算术扩展。在后一种情况下,字符序列\<newline>被忽略,并且\来引用字符\$`

如果重定向运算符为<<- ,则所有前导制表符将从输入行和包含定界符的行中除去。这允许以自然的方式缩进 shell 脚本中的 here-document。

在您的情况下,“EOF” 被称为 “此处标签”。基本上, <<Here告诉外壳程序您将要输入多行字符串,直到 “tag” Here为止。您可以根据需要命名该标签,通常是EOFSTOP

有关 Here 标记的一些规则:

  1. 标记可以是任何字符串,可以是大写或小写,尽管大多数人习惯上都使用大写。
  2. 如果该行中还有其他单词,则该标签将不被视为 Here 标签。在这种情况下,它将仅被视为字符串的一部分。标签本身应位于单独的行上,才能视为标签。
  3. 标签在该行中不应包含任何前导或尾随空格,才能将其视为标签。否则,它将被视为字符串的一部分。

例子:

$ cat >> test <<HERE
> Hello world HERE <-- Not by itself on a separate line -> not considered end of string
> This is a test
>  HERE <-- Leading space, so not considered end of string
> and a new line
> HERE <-- Now we have the end of the string