假设我有一个文件Foo.in
:
Contents of Foo
和Bar.in
INSERT Foo.in
Contents of Bar
我想编写一个sed
脚本,将INSERT xyz
替换为xyz
文件的实际内容。在这个特定的例子中,我想生成包含以下内容的Bar.out
文件:
Contents of Foo
Contents of Bar
我考虑使用sed
的{{1}}命令作为演示in this Stack Overflow question,但问题是要插入的文件的名称是在文件本身中指定的。我考虑过扫描r
命令的文件,然后分别为找到的每个INSERT
运行sed
,但这是一个O(n ^ 2)复杂度的可怕解决方案。我更喜欢使用sed或AWK来做这件事,但如果所有其他方法都失败了,Perl脚本就可以接受。
答案 0 :(得分:3)
$ cat Foo.in
Contents of Foo
$ cat Bar.in
INSERT Foo.in
Contents of Bar.in
$ awk '/INSERT/{while((getline line < $2) > 0 ){print line}close($2);next}1' Bar.in
Contents of Foo
Contents of Bar.in
答案 1 :(得分:1)
这很容易做到。这是一个小的Perl脚本:
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
while(<>) {
# If this line is an INSERT command, capture the filename and insert it
if (my ($filename) = /^INSERT\s+(.+)$/) {
open my $fh, "<", $filename;
local $/;
print <$fh>;
}
# Otherwise just print out the line as it is.
else {
print;
}
}
用法:$ perl the-script.pl some_file.txt > output.txt
此解决方案存在一些问题:插入文件中的INSERT
将不会被处理。 INSERT
中的文件路径相对于调用的工作目录而不是发布INSERT
的文件进行解释。
答案 2 :(得分:1)
Amon使用你的正则表达式,
perl -MFile::Slurp -pe '$_= read_file($1) if /^INSERT\s+(.+)$/' file
答案 3 :(得分:1)
$ cat Foo.in
Contents of Foo
INSERT test
$ cat test
1
2
3
4
5
$ cat Bar.in
INSERT Foo.in
Contents of Bar.in
AWK代码:
awk '
function fetch(inp){
while( (getline p < inp) > 0)
print p
close(inp)
}
/INSERT/{
while((getline line < $2) > 0)
{
if(line ~ /INSERT/){
split(line,A)
fetch(A[2])
next
}
else{
print
}
}
close($2)
next
}1
' Bar.in
结果:
INSERT Foo.in
1
2
3
4
5
Contents of Bar.in
<强> --- ---编辑强>
$ cat test.awk
function fetch(inp){
while( (getline p < inp) > 0)
print p
close(inp)
}
/INSERT/{
while((getline line < $2) > 0)
{
if(line ~ /INSERT/){
split(line,A)
fetch(A[2])
next
}
else{
print
}
}
close($2)
next
}1
用法:
$ awk -f test.awk Bar.in
答案 4 :(得分:0)
您也可以在不加载Perl模块的情况下执行此操作,只需更少的字符:
perl -pe 'open $F,"<$1" and $_=<$F> if /^INSERT\s+(.+)$/' [file]