在bash中"cat << EOF"是如何工作的

2023-12-28 08:12:02 浏览数 (3)

问:

我需要编写一个脚本来向程序(psql)输入多行输入。 在谷歌一番搜索之后,我发现以下语法是有效的:

代码语言:javascript复制
cat << EOF | psql ---params
BEGIN;

`pg_dump ----something`

update table .... statement ...;

END;
EOF

这正确地构造了多行字符串(从BEGIN; 到END;,包括在内),并通过管道输入给psql。

但是我不知道它是如何工作的,有人能解释一下吗?

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

<<到底是做什么的? 它有man page吗?

答:

源自man bash:

Here Documents

这种重定向指示shell从当前源读取输入,直到看到只包含word的行(后面没有空格)。读取到该点的所有行都将用作命令的标准输入(或者文件描述符n,如果指定了n)。

here-documents的格式是:

代码语言:bash复制
          <<[-]word
                  here-document
          delimiter

word上不执行参数扩展、命令替换、算术扩展或路径名扩展。如果word中的任何字符被加引号,则分隔符是word中删除引号的结果,并且here-document中的行不会展开。如果word没有加引号,那么here-document的所有行都要进行参数扩展、命令替换和算术扩展。在后一种情况下,字符序列 <newline> 被忽略,必须使用(反斜线)来引用字符 $`

如果重定向操作符是<<-,则从输入行和包含分隔符的行中删除所有前导制表符。这使得shell脚本中的here-documents可以以一种自然的方式缩进。

为了便于理解 word 不加引号加了引号的区别,我们可以做一个测试,运行截图如下:

Here Documents 是一种强大的工具,可以用来向脚本或命令提供复杂的多行输入,例如 SQL 查询、配置文件内容等。

常见用法:

1. 将多行字符串赋值给shell变量

代码语言:bash复制
$ sql=$(cat <<EOF
SELECT foo,bar FROM db
WHERE foo='baz'
EOF
)

2. 在Bash中将多行字符串传递给一个文件

代码语言:bash复制
$ cat <<EOF > print.sh
#!/bin/bash
echo $PWD
echo $PWD
EOF

3. 在Bash中将多行字符串传递给管道

代码语言:bash复制
$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF

参考文档:

  • stackoverflow question 2500436
  • https://www.gnu.org/software/bash/manual/bash.html#Here-Documents

1 人点赞