Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
自动将指定文件插入另一个文件(使用sed、AWK或Perl)_Perl_Bash_Sed_Awk - Fatal编程技术网

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

自动将指定文件插入另一个文件(使用sed、AWK或Perl),perl,bash,sed,awk,Perl,Bash,Sed,Awk,假设我有一个文件,Foo.in: Contents of Foo 和Bar.in INSERT Foo.in Contents of Bar 我想编写一个sed脚本,用xyz文件的实际内容替换INSERT xyz。在这个特定的示例中,我希望生成包含以下内容的Bar.out文件: Contents of Foo Contents of Bar 我曾考虑使用演示过的sed的r命令,但问题是要插入的文件名是在文件本身中指定的。我考虑过扫描文件中的INSERT命令,然后对找到的每个INSERT分别

假设我有一个文件,
Foo.in

Contents of Foo
Bar.in

INSERT Foo.in
Contents of Bar
我想编写一个
sed
脚本,用
xyz
文件的实际内容替换
INSERT xyz
。在这个特定的示例中,我希望生成包含以下内容的
Bar.out
文件:

Contents of Foo
Contents of Bar
我曾考虑使用演示过的
sed
r
命令,但问题是要插入的文件名是在文件本身中指定的。我考虑过扫描文件中的
INSERT
命令,然后对找到的每个
INSERT
分别运行
sed
,但这是一个非常糟糕的解决方案,复杂性为O(n^2)。我更愿意使用sed或AWK来实现这一点,但如果其他方法都失败了,则可以使用Perl脚本。

$cat Foo.in
$ 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
食物内容 $cat Bar.in 插入Foo.in 酒吧的内容 $awk'/INSERT/{while((getline<$2)>0){print line}close($2);next}1'Bar.in 食物内容 酒吧的内容
这很容易做到。下面是一个小的Perl脚本:

#/usr/bin/env perl
严格使用;
使用警告;
使用自动模具;
while(){
#如果此行是INSERT命令,则捕获文件名并将其插入
如果(我的($filename)=/^INSERT\s+(.+)$/){
使用正则表达式打开我的$fh,“Amon

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

您也可以在不加载Perl模块的情况下使用更少的字符执行此操作:

perl -pe 'open $F,"<$1" and $_=<$F> if /^INSERT\s+(.+)$/' [file]
perl-pe'open$F,“递归
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
---编辑---

$ 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

我认为是O(n)。但更重要的是,除非你有数千个文件,并且每隔一天就需要这样做,否则为什么要关心渐进的复杂性。如果问题真的是由资源决定的,那么两种脚本语言都不是正确的答案。编辑:等等,这是关于只对一个文件这样做吗?那么复杂性完全没有意义…我有很多文件如果我扫描每个文件N次(其中N是插入杂注的数量),那么复杂性是O(N^2),而不是O(N)。我同意这不是一个大问题,但这表明设计不好。正如您所提到的,如果要插入的内容是sed脚本中用作引用的值,则sed不会替换动态内容。文件名是“硬编码”的。现在您可以动态创建一个sed脚本,但在本例中,如果n是pragma的数量,则awk要好得多。对不起,在脚本的世界中,我会在脑海中保留一句话:“Perl脚本是“正确的”“如果你开始考虑运行时效率和资源管理,Perl可能是一种错误的语言,对于sed和awk来说,这很可能是正确的。有可能让这个解决方案递归地工作吗?@Jan Stolarek我刚刚在另一篇文章中发了帖子,请看一看……嗯……看起来我对我来说不起作用。我也试着把它放到一个文件中,并用
-f
选项运行
awk
,但运气不好。像这样试试
awk-f test.awk吧。在
中,我试过了。它似乎不起作用:-/在编辑中检查测试文件的内容,看起来你删除了
。在
中,顺便问一下,有什么错误或者消息?没有错误消息-没有任何东西被替换。当我用原始的、非递归的版本替换递归版本时,一切都很好。
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