Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.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
Perl 将具有可变列数的可变行数转换为<;模式>;然后是所有行,直到下一行<;模式>;_Perl_Awk_Sed_Text Processing - Fatal编程技术网

Perl 将具有可变列数的可变行数转换为<;模式>;然后是所有行,直到下一行<;模式>;

Perl 将具有可变列数的可变行数转换为<;模式>;然后是所有行,直到下一行<;模式>;,perl,awk,sed,text-processing,Perl,Awk,Sed,Text Processing,我有以下输入,与网络设备的多接口(几十个)相关(请注意,#行仅用于澄清,数据中不存在): eth #eth模式良好,将处理运行编号 参数1参数2参数3…参数 #省略号的意思是等等,不是字面意思 参数21参数22 参数31参数32参数33参数34 参数41 以太 参数1参数2 参数21 . . . . 参数1参数2 #同样,垂直省略号不是字面意义上的,只是表示行 #随着参数的不断变化,这是不知道的 #多久 以太 参数1参数2 以太 参数1参数2 参数21 所需的输出应如下所示: eth<n

我有以下输入,与网络设备的多接口(几十个)相关(请注意,
#
行仅用于澄清,数据中不存在):

eth
#eth模式良好,将处理运行编号
参数1参数2参数3…参数
#省略号的意思是等等,不是字面意思
参数21参数22
参数31参数32参数33参数34
参数41
以太
参数1参数2
参数21
.
.
.
.
参数1参数2
#同样,垂直省略号不是字面意义上的,只是表示行
#随着参数的不断变化,这是不知道的
#多久
以太
参数1参数2
以太
参数1参数2
参数21
所需的输出应如下所示:

eth<number1> parameter1 parameter2 parameterN parameter21 parameter22 parameter31 parameter32 parameter33 parameter34 parameter41 
# all in one line, with as many columns as there are parameters for 
# the given interface.
eth<number2> parameter1 parameter2....parameterNM
eth<number3> parameter1 parameter2
eth<number4> parameter1 parameter2 parameter21
eth参数1参数2参数21参数22参数31参数32参数33参数34参数41
#所有列都在一行中,列的数量与参数的数量相同
#给定的接口。
eth参数1参数2…参数M
eth参数1参数2
eth参数1参数2参数21

有没有办法最好用
awk
sed
来完成它?当然,欢迎提出任何澄清问题

这在Perl中应该很容易做到。
eth
行很容易匹配,我们只想将它们之间的所有行组合成一行

#!/usr/bin/env perl
use strict;
use warnings;

my $collected;
while (my $line = <DATA>){
  next if $line =~ /^#/;
  if($line =~ /^eth/) {
    # new block of lines
    if ($collected) {
      print $collected, "\n";
      $collected = "";
    }
    chomp $line;
    $collected = $line;
  } else {
    # Append to collected lines
    chomp $line;
    $collected = "$collected $line";
  }
}
print $collected,"\n" if $collected;
__DATA__
eth<number1>
parameter1 parameter2 parameter3...parameterN
#ellipsis means and so on and is not literal
parameter21 parameter22
parameter31 parameter32 parameter33 parameter34
parameter41
eth<number2>
parameter1 parameter2
parameter21
parameterN1 parameterN2
eth<number3>
parameter1 parameter2
eth<number4>
parameter1 parameter2
parameter21
这可能适用于您(GNU-sed):

有三种情况:以
#
开头的行、以“eth”开头的行和其他行

如果当前行是注释,请将其删除

如果当前行没有开始,请将其附加到保留空间(HS)并删除,除非它是最后一行


否则,当前行开始于
eth
或是最后一行,因此切换到HS,如果其中包含任何换行符,则将其替换为空格并打印结果。调回图案空间,用当前行替换HS,并删除当前行,除非它是文件的最后一行,在这种情况下,打印它。

是的,它可以,并且很清楚如何操作(将可以意味着它足够好和通用,可以与实际输出一起执行)。在您看来,awk不适合这种类型的任务?我确信使用
awk
是可能的,但对我来说,使用Perl编写它更容易。去掉示例中的所有
,这样我们就可以测试潜在的解决方案,并添加您迄今为止尝试过的内容。看看是否还不清楚。这很优雅!也许(而且很可能)我不够清楚,对此我很抱歉,但这不是字面意义上的,因为在输入中找不到-我试图表示给定接口的运行编号。在严酷的现实中,它看起来像:eth 1-43;eth 1-44;eth 2-36;eth 2-37等等,原则上,在这些行下面表示为参数的东西很可能包含相同的数字模式。@Proton--好的,我仍然在理解sed咒语(包括HS的概念),但是,非常清楚的是最后一行(行)对于最后一个eth条目,既被转置到最后一列,也被打印为最后一行。因此,在示例输入中,它将是parameter21,既作为包含eth的行的最后一列,也作为单独的行打印出来。“你可以自己试试。”波通,只有几分钟的空闲时间——它仍然会打印两次。示例输入具有足够的代表性。
#!/usr/bin/env perl
use strict;
use warnings;

my $collected;
while (my $line = <DATA>){
  next if $line =~ /^#/;
  if($line =~ /^eth/) {
    # new block of lines
    if ($collected) {
      print $collected, "\n";
      $collected = "";
    }
    chomp $line;
    $collected = $line;
  } else {
    # Append to collected lines
    chomp $line;
    $collected = "$collected $line";
  }
}
print $collected,"\n" if $collected;
__DATA__
eth<number1>
parameter1 parameter2 parameter3...parameterN
#ellipsis means and so on and is not literal
parameter21 parameter22
parameter31 parameter32 parameter33 parameter34
parameter41
eth<number2>
parameter1 parameter2
parameter21
parameterN1 parameterN2
eth<number3>
parameter1 parameter2
eth<number4>
parameter1 parameter2
parameter21
open my $fh, "<", "your.data" or die "Can't open file: $!\n";
...
while(my $line = <$fh>) { 
...
sed -E '/^#/d;/^eth/!{H;$!d};x;s/\n/ /gp;x;h;d' file