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



假设我有一个文件,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

我想过使用 sedr 命令,如这个堆栈 溢出问题所示,但问题是要插入的文件的名称是在文件本身中指定的。我想过扫描文件中的INSERT命令,然后为每个找到的INSERT分别运行sed,但这是一个具有 O(n^2) 复杂性的可怕解决方案。我更喜欢使用 sed 或 AWK 来做到这一点,但如果所有其他方法都失败了,Perl 脚本是可以接受的。

$ 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

这很容易做到。下面是一个小的 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) = /^INSERTs+(.+)$/) {
    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

此解决方案存在一些问题:不会处理插入文件中的INSERTINSERT中的文件路径是相对于调用的工作目录而不是相对于发出INSERT的文件进行解释的。

阿蒙使用你的正则表达式,

perl -MFile::Slurp -pe '$_= read_file($1) if /^INSERTs+(.+)$/' file

递归

$ 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

你也可以在不加载Perl模块的情况下做到这一点,字符更少:

perl -pe 'open $F,"<$1" and $_=<$F> if /^INSERTs+(.+)$/' [file]

相关内容

  • 没有找到相关文章

最新更新