我需要编写一个脚本,向程序(psql)输入多行输入。

在谷歌搜索了一下之后,我发现下面的语法是有效的:

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

`pg_dump ----something`

update table .... statement ...;

END;
EOF

这正确地构造了多行字符串(从BEGIN;to END;,包括在内)并将其作为输入管道输送到psql。

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

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

<<到底是做什么的?

它有手册页吗?


当前回答

需要注意的是,cat << \EOT(参见反斜杠)不会展开内部的任何变量,而cat << EOT则可以。

例子:

FOO="bar"

cat << \EOT > foobar.txt
echo "$FOO"
EOT

将输出: echo $ FOO

而:

FOO="bar"

cat << EOT > foobar.txt
echo "$FOO"
EOT

将输出: 回声“酒吧”

其他回答

在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文件包含bar和baz行。相同的输出被打印到stdout。

对上面的答案做一点扩展。后面的>将输入引导到文件中,覆盖现有内容。然而,一个特别方便的用法是双箭头>>追加,将您的新内容添加到文件的末尾,如:

cat <<EOF >> /etc/fstab
data_server:/var/sharedServer/authority/cert /var/sharedFolder/sometin/authority/cert nfs
data_server:/var/sharedServer/cert   /var/sharedFolder/sometin/vsdc/cert nfs
EOF

这将扩展fstab,而不必担心意外修改其中的任何内容。

在你的例子中,“EOF”被称为“Here Tag”。基本上,<<Here告诉shell,您将输入一个多行字符串,直到“tag”在这里。你可以随意命名这个标签,通常是EOF或STOP。

关于Here标签的一些规则:

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

例子:

$ 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

长话短说,EOF标记(但也可以使用不同的文字)是一种heredoc格式,允许您以多行方式提供输入。 很多困惑来自于猫实际上是如何工作的。 你可以使用cat >>或>,如下所示:

$ cat >> temp.txt
line 1
line 2

虽然在手动写入控制台时可以这样使用cat,但如果我想以一种更声明性的方式提供输入,以便工具可以重用它,并保留缩进、空格等,则不方便。 Heredoc允许定义您的整个输入,就好像您不是在使用stdin,而是在单独的文本编辑器中输入一样。这是维基百科文章的意思:

它是源代码文件的一个部分,它被当作 单独的文件中。

创建json文件的示例:

cat << EoF > ./allaccess.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ]
    }
  ]
}
EoF

结果是:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ]
    }
  ]
}