Search code examples
perl

How to append zero based on the length of the input type?


I have multiple input lines in a file, and I want to search for a specific type in a line (search for Tr16 or Tr32). If the match is found, then I want to append zero with the corresponding value. But I want to ignore if the length of the value is greater than 3.

Ignore for these lines:

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

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

Replace for these lines:

  1. If its Tr16 or Sr16 then append the string value with zero

     { 0,  corresponding value}
    

for e.g.

    x317_dwsrp  { 0, 2 }    Tr16, selection
  1. If its Tr32 then append with

     { 0, 0, 0, corresponding value }
    

for e.g.

    x315_conex  { 0, 0, 0, 1 }  Tr32, selection

My input lines:

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 

Code:

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 $_;
}

My expected output:

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 

Here I was doing based on replacement, but what could be optimized way?


Solution

  • You have to escape the curly brackets in the replacement part, and there is no need for the g flag.

    I've added a limit to 3 digits:

    #!/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 
    

    Output:

    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 
    

    A more simple code:

    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;
    }