Here Document

Here Document 是一种在脚本中嵌入多行文本的方式。它把标记之间的内容当作标准输入传递给命令,比多次 echo 更清晰,适合生成配置文件、发送邮件等场景。

基本语法

命令 << 标记
内容
标记

标记可以是任意字符串,常用 EOF 或 END:

cat << EOF
这是第一行
这是第二行
这是第三行
EOF

运行结果:

这是第一行
这是第二行
这是第三行

变量替换

默认情况下,Here Document 中的变量会被替换:

name="张三"
cat << EOF
你好,$name
当前目录:$PWD
时间:$(date)
EOF

运行结果:

你好,张三
当前目录:/home/user
时间:2024-03-15 10:00:00

禁用变量替换

用单引号包裹标记,禁用变量替换:

cat << 'EOF'
变量不会被替换:$name
命令也不会执行:$(date)
EOF

运行结果:

变量不会被替换:$name
命令也不会执行:$(date)

这在写脚本模板时很有用。

去除行首制表符

<<- 会忽略行首的制表符(不是空格),方便脚本缩进:

if true; then
    cat <<- EOF
		第一行
		第二行
		第三行
	EOF
fi

注意:结束标记的缩进也必须是制表符。

写入文件

cat << EOF > config.txt
server {
    listen 80;
    server_name example.com;
    root /var/www/html;
}
EOF

追加写入:

cat << EOF >> config.txt
# 新增配置
location /api {
    proxy_pass http://localhost:8080;
}
EOF

发送邮件

mail -s "报告" admin@example.com << EOF
这是邮件正文。
第一行内容。
第二行内容。
EOF

传递给函数

process() {
    while read line; do
        echo "处理:$line"
    done
}

process << EOF
数据1
数据2
数据3
EOF

在 ssh 中使用

ssh user@server << EOF
cd /var/www
git pull
npm install
npm run build
EOF

多个 Here Document

cat << EOF
第一个文档
EOF

cat << EOF
第二个文档
EOF

嵌套使用

Here Document 不能直接嵌套,但可以通过函数间接实现:

outer() {
    cat << EOF
外部内容
$(inner)
外部内容继续
EOF
}

inner() {
    cat << EOF
    内部内容
EOF
}

outer

Here String

Here String 是 Here Document 的简化形式,用于单行输入:

grep "pattern" <<< "这是一行测试文本"
read a b c <<< "1 2 3"
echo "a=$a, b=$b, c=$c"

运行结果:

a=1, b=2, c=3

Here String 也支持变量替换:

name="world"
grep "world" <<< "hello $name"

禁用替换:

grep '$name' <<< 'hello $name'

实用示例

生成配置文件

cat << EOF > /etc/nginx/conf.d/app.conf
server {
    listen 80;
    server_name $(hostname);
    
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host \$host;
    }
}
EOF

注意 $host 要转义,否则会被替换。

创建脚本

cat << 'EOF' > deploy.sh
#!/bin/bash
echo "开始部署..."
git pull
npm install
npm run build
echo "部署完成"
EOF

chmod +x deploy.sh

批量创建用户

while read username password; do
    useradd -m "$username"
    echo "$username:$password" | chpasswd
done << EOF
user1 pass1
user2 pass2
user3 pass3
EOF

生成 JSON

cat << EOF
{
    "name": "$name",
    "age": $age,
    "city": "$city"
}
EOF

SQL 批量操作

mysql -u root -p << EOF
USE mydb;
CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100)
);
INSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');
EOF

小结

  • Here Document 用于嵌入多行文本
  • << 标记 开始,标记结束
  • 默认进行变量替换,<< '标记' 禁用替换
  • <<- 忽略行首制表符
  • Here String <<< 用于单行输入
  • 常用于生成配置文件、发送邮件、远程执行命令