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 user@server << EOF
cd /var/www
git pull
npm install
npm run build
EOF
cat << EOF
第一个文档
EOF
cat << EOF
第二个文档
EOF
Here Document 不能直接嵌套,但可以通过函数间接实现:
outer() {
cat << EOF
外部内容
$(inner)
外部内容继续
EOF
}
inner() {
cat << EOF
内部内容
EOF
}
outer
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
cat << EOF
{
"name": "$name",
"age": $age,
"city": "$city"
}
EOF
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
<< 标记 开始,标记结束<< '标记' 禁用替换<<- 忽略行首制表符<<< 用于单行输入