给定两个文件,第一个是Apache配置文件:
$ cat vhosts-ssl.conf
<VirtualHost *:443>
vhost 1
foobar 1
foobar 2
barfoo 1
barfoo 2
</VirtualHost>
<VirtualHost *:443>
vhost 2
foobar 2
barfoo 1
foobar 1
barfoo 2
</VirtualHost>
<VirtualHost *:443>
vhost 3
foobar 1
barfoo 1
foobar 2
barfoo 2
</VirtualHost>
<VirtualHost *:443>
vhost 4
foobar 1
foobar 2
barfoo 1
barfoo 2
</VirtualHost>
第二个文件包含应添加到一个(变量)特定VirtualHost块的末尾的行:
$ cat inserted.txt
inserted line 1
inserted line 2
结果应如下所示:
$ cat vhosts-ssl.conf
<VirtualHost *:443>
vhost 1
foobar 1
foobar 2
barfoo 1
barfoo 2
</VirtualHost>
<VirtualHost *:443>
vhost 2
foobar 2
barfoo 1
foobar 1
barfoo 2
inserted line 1
inserted line 2
</VirtualHost>
<VirtualHost *:443>
vhost 3
foobar 1
barfoo 1
foobar 2
barfoo 2
</VirtualHost>
<VirtualHost *:443>
vhost 4
foobar 1
foobar 2
barfoo 1
barfoo 2
</VirtualHost>
我尝试了以下sed的一些变体,但是没有做到这一点:
$ sed -e '/^<VirtualHost/{:a;n;/^<\/VirtualHost/\!ba;r inserted.txt' -e '}' vhosts-ssl.conf
我无法弄清楚如何只选择我需要插入文件的一个VirtualHost块,因为我使用FreeBSD sed(或awk)我也使用之前的sed命令得到此错误:
$ sed -e '/^<VirtualHost/{:a;n;/^<\/VirtualHost/\!ba;r inserted.txt' -e '}' vhosts-ssl.conf
sed: 2: "}
": unused label 'a;n;/^<\/VirtualHost/!ba;r inserted.txt'
使用GNU sed我得到这个输出:
$ gsed -e '/^<VirtualHost/{:a;n;/^<\/VirtualHost/\!ba;r inserted.txt' -e '}' vhosts-ssl.conf
<VirtualHost *:443>
vhost 1
foobar 1
foobar 2
barfoo 1
barfoo 2
</VirtualHost>
inserted line 1
inserted line 2
<VirtualHost *:443>
vhost 2
foobar 2
barfoo 1
foobar 1
barfoo 2
</VirtualHost>
inserted line 1
inserted line 2
<VirtualHost *:443>
vhost 3
foobar 1
barfoo 1
foobar 2
barfoo 2
</VirtualHost>
inserted line 1
inserted line 2
<VirtualHost *:443>
vhost 4
foobar 1
foobar 2
barfoo 1
barfoo 2
</VirtualHost>
inserted line 1
inserted line 2
由于我想了解我的错误并从他们那里学习,我希望得到一些解释的答案,甚至可能还有一些链接到rtfm,谢谢。
已添加2016-10-16
伪代码:
if BLOCK begins with /^<VirtualHost/
and ends with /^<\/VirtualHost/
and is the ${n-th} BLOCK
in FILE_1
then insert content of FILE_2
before last line of ${n-th} BLOCK
without touching rest of FILE_1
endif
save modified FILE_1
$ {n-th}收集于:
$ httpd -t -D DUMP_VHOSTS | \
grep -i "${SUBDOMAIN}.${DOMAIN}" | \
awk '/^[^\ ]*:443[\ ]*/ {print $3}' | \
sed -e 's|(\(.*\))|\1|' | \
cut -d: -f2
输出是我想通过FILE_2
扩展的BLOCK的编号请在FreeBSD上只使用非GNU版本,谢谢。
答案 0 :(得分:2)
awk
救援!
需要多个字符记录分隔符,由gawk
$ awk 'NR==FNR{insert=$0; next}
{print $0 (FNR==2?insert:"") RT}' RS='^$' insert.file RS="</VirtualHost>" file
读完第一个文件并分配给变量insert,同时在第二个记录末尾迭代第二个文件,在记录内容后打印变量。
普通awk
$ awk 'NR==FNR{insert=insert?insert ORS $0:$0; next}
/<\/VirtualHost>/ && ++c==2{print insert} 1' insert.file file
答案 1 :(得分:0)
在GNU sed
(以及BusyBox sed
)a
,b
,c
,i
之后的文件/标签/文字,r
,t
,w
和:
命令可以用分号分隔,而在其他版本的sed
中,文件/标签/文字可以分隔只能用换行符分隔。
这种行为意味着第一个字符串不是定义标签a
,而是定义标签
a;n;/^<\/VirtualHost/\!ba;r inserted.txt
,就像单独使用-e
作为右括号一样,脚本必须在标签和分支之后分开。
(另外,!
不得转义)
sed -e '/^<VirtualHost/{:a' -e 'n;/^<\/VirtualHost/!ba' \
-e 'r inserted.txt' -e '}' vhosts-ssl.conf
或者,脚本可以跨越多行:
sed '/^<VirtualHost/ {
:a
n
/^<\/VirtualHost/!ba
r inserted.txt
}' vhosts-ssl.conf
请注意,在必须转义换行符的情况下,此拆分可能不起作用;例如,使用a
,c
和i
命令时。
答案 2 :(得分:0)
假设:
$ cat f1.txt
line 1
line 2
line 3
INSERT HERE
line 4
line 5
$ cat f2.txt
INSERTED LINE 1
INSERTED LINE 2
你可以这样做:
$ awk 'BEGIN{fc=""} FNR==NR{fc=fc $0 "\n";next} /^INSERT HERE/{printf "%s", fc; next} 1' f2.txt f1.txt
line 1
line 2
line 3
INSERTED LINE 1
INSERTED LINE 2
line 4
line 5