问:
我需要编写一个脚本来向程序(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