如何根据输入类型的长度追加零

时间:2016-11-03 12:39:34

标签: perl

假设我在文件中有多个输入行,我想在一行中搜索特定类型(搜索Tr16或Tr32)。如果找到匹配,那么我想用相应的值追加零。但是如果值的长度大于3,我想忽略。

忽略这一行:

connect_next_frame  1234    Tr16, selection # since value is greater than >3

time_scheduler  76890    Tr32, selection  #  since value is greater than >3

替换这些行:

  1. 如果它的Tr16或Sr16然后将字符串值附加为零

    { 0,  corresponding value}
    

    例如。

    x317_dwsrp  { 0, 2 }    Tr16, selection
    
  2. 如果其Tr32随后附加

    { 0, 0, 0, corresponding value }
    

    例如。

    x315_conex  { 0, 0, 0, 1 }  Tr32, selection
    
  3. 我的输入行:

    x317_dwsrp  2   Tr16, selection 
    x315           4     Tr16, selection        
    user_info 20    Tr16, selection 
    sib_pos    8   Sr16, selection  
    dma_frame   1   Tr32, selection 
    x315_conex  1   Tr32, selection 
    

    代码:

    use strict;
    use warnings;
    
    my $inputfile  = 'test_input.txt';
    my $outputfile = 'test_output.txt';
    
    open my $my_ipfh, "<", $inputfile or die $!;
    
    open my $my_opfh, ">", $outputfile or die $!;
    
    while (<$my_ipfh>)
    { 
    
    if (/Tr16|Sr16|Tr32/)
    {
     s/x317_dwsrp   (\d+)    Tr16, selection/x317_dwsrp  { 0, $1 }   Tr16, selection/g;
     s/x315     (\d+)    Tr16, selection/x315       { 0, $1 }    Tr16, selection/g;     
     s/user_info    (\d+)    Tr16, selection/user_info  { 0, $1 }    Tr16, selection/g; 
     s/sib_pos    (\d+)       Sr16, selection/sib_pos    { 0, $1 }      Sr16, selection/g;  
     s/tdma_frame   (\d+)   Tr32, selection/tdma_frame  { 0, 0, 0, $1 } Tr32, selection/g;
     s/x315_conex   (\d+)   Tr32, selection/x315_conex  { 0, 0, 0, $1 } Tr32, selection/g;  
    }
    
     print $my_opfh $_;
    }
    

    我的预期输出:

    x317_dwsrp   { 0, 2 }    Tr16, selection    
    x315        { 0, 4 }     Tr16, selection        
    user_info   { 0, 20 }    Tr16, selection    
    sib_pos    { 0, 8 }      Sr16, selection    
    tdma_frame  { 0, 0, 0, 1 }  Tr32, selection 
    x315_conex  { 0, 0, 0, 1 }  Tr32, selection 
    

    我在这里做的是基于替换,但可以优化的方式?

2 个答案:

答案 0 :(得分:1)

以下是重现输出的更通用的方法:

use warnings;
use strict;

while (<DATA>) {
    if (/(\d+)\s+[ST]r(16|32)/) {
        my $n = $1;
        my $r = $2;
        if (length $n < 4) {
            my $zeroes = ($r == 16) ? '0,' : '0, 0, 0,';
            s/(\s+)(\d+)(\s+)/$1\{ $zeroes $2 }$3/;
        }
    }
    print;
}

__DATA__
   x317_dwsrp   2   Tr16, selection 
   x315        4     Tr16, selection        
   user_info 20 Tr16, selection 
   sib_pos    8   Sr16, selection   
  tdma_frame    1   Tr32, selection 
  x315_conex    1   Tr32, selection 

答案 1 :(得分:1)

你必须逃避替换部分中的花括号,不需要g标志。

我已将限制添加到3位数:

#!/usr/bin/perl
use Modern::Perl;

while (<DATA>) { 
    chomp;
    s/(x317_dwsrp\s+)(\d{1,3})(\s+Tr16, selection)/$1\{ 0, $2 \}$3/;
    s/(x315\s+)(\d{1,3})(\s+Tr16, selection)/$1\{ 0, $2 \}$3/;
    s/(user_info\s+)(\d{1,3})(\s+Tr16, selection)/$1\{ 0, $2 \}$3/;
    s/(sib_pos\s+)(\d{1,3})(\s+Sr16, selection)/$1\{ 0, $2 \}$3/;
    s/(tdma_frame\s+)(\d{1,3})(\s+Tr32, selection)/$1\{ 0, 0, 0, $2 \}$3/g;
    s/(x315_conex\s+)(\d{1,3})(\s+Tr32, selection)/$1\{ 0, 0, 0, $2 \}$3/;
    say;
}


__DATA__
x317_dwsrp   2   Tr16, selection
x315        4     Tr16, selection        
user_info 20 Tr16, selection 
sib_pos    8   Sr16, selection   
tdma_frame    1   Tr32, selection 
x315_conex    1   Tr32, selection 

<强>输出:

x317_dwsrp   { 0, 2 }   Tr16, selection
x315        { 0, 4 }     Tr16, selection        
user_info { 0, 20 } Tr16, selection 
sib_pos    { 0, 8 }   Sr16, selection   
tdma_frame    { 0, 0, 0, 1 }   Tr32, selection 
x315_conex    { 0, 0, 0, 1 }   Tr32, selection 

更简单的代码:

while (<DATA>) { 
    chomp;
    s/(.+\s)(\d{1,3})(\s+[ST]r16, selection)/$1\{ 0, $2 \}$3/;
    s/(.+\s)(\d{1,3})(\s+Tr32, selection)/$1\{0, 0, 0, $2 \}$3/g;
    say;
}