自动将指定文件插入另一个文件(使用sed,AWK或Perl)

时间:2014-02-19 11:55:25

标签: perl bash sed awk

假设我有一个文件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脚本就可以接受。

5 个答案:

答案 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]