sam sam - 1 month ago 10
Perl Question

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

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

Ignore for this 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

  2. 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?

Answer

Here is a more generalized way to reproduce your output:

use warnings;
use strict;

while (<DATA>) {
    if (/(\d+)\s+[ST]r(\d+)/) {
        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