0

I'm new to sed, and recently get some problems as below :

{ parameter S0=7'd0, S1=7'd1, S2=7'd2, S3=7'd3, S4=7'd4,                      
S5=7'd5, S6=7'd6, S7=7'd7, S8=7'd8, S9=7'd9, 
S10=7'd10, S11=7'd11, S12=7'd12, S13=7'd13, S14=7'd14, 
S15=7'd15, S16=7'd16, S17=7'd17, S18=7'd18, S19=7'd19,
S20=7'd20, S21=7'd21, S22=7'd22, S23=7'd23, S24=7'd24,
S25=7'd25, S26=7'd26, S27=7'd27, S28=7'd28, S29=7'd29,
S30=7'd30, S31=7'd31, S32=7'd32, S33=7'd33, S34=7'd34,
S35=7'd35;  }

I have a list of string like ['10' '5' '30' ... ] then I want to match the pattern 7'd0, 7'd1, 7'd2..., then replace them to 7'd10, 7'd5, 7'd30 ....

what is the best way to do this? must use forloop to do this?

10
  • Remove the image and put it as a text
    – Inian
    Commented Jan 23, 2018 at 7:58
  • Please don't post screenshots of text. Copy and paste the text itself into your question and format it as code with the {} icon in the editor.
    – cas
    Commented Jan 23, 2018 at 8:10
  • 1
    sorry, i had replaced the image to text Commented Jan 23, 2018 at 9:49
  • Are newlines significant in the first format? Is that data in a file? The list, is that also stored in a file in the format shown?
    – Kusalananda
    Commented Jan 23, 2018 at 9:53
  • newlines are not significant, the first format is a part of a file, and the list is an other file that contain some integers separated by white space Commented Jan 23, 2018 at 10:03

1 Answer 1

0
#!/usr/bin/perl

use strict;
use Sort::Naturally;   # CPAN module to perform Natural Sorts.

# should do real option/argument processing here.  this is good enough
# for this example.
my $params  = shift || 'params.txt';
my $strings = shift || 'strings.txt';

my %params=();  # hash to hold each parameter

# read in the parameters file.
open(PARAMS,"<",$params) || die "couldn't open $params: $!";
while(<PARAMS>) {
  # clean up input, discard everything that would complicate splitting
  # into comma-separated fields.
  s/^\s*\{\s*parameter\s+//;
  s/\s*;\s*\}//;
  s/^\s*|\s*$//g;
  s/\s*,$//;   # / this comment fixes stack exchange\'s broken syntax colouring
  chomp;

  # split each input line into an array, with comma as separator
  my @F = split /\s*,\s*/;   # /

  # use each array element to populate the %params hash
  foreach my $f (@F) {
    my ($key,$val) = split /\s*=\s*/, $f;    # /
    $params{$key} = $val;
  };
};
close(PARAMS);

# read in the strings file and apply changes to %params
# this assumes that the strings file contains new values for 
# all paramaters and that they are listed one-per-line in order (0..35)
open(STRING,"<",$strings) || die "couldn't open $strings: $!";
my $lineno = 0;
while(<STRING>) {
  s/^\s*|\s*$//g; # remove leading/trailing whitespace
  s/#.*//;        # ignore comments
  next if (/^$/);

  $params{'S'.$lineno++} = "7'd$_";
};
close(STRING);

# natural-sort %params keys
my @keys = nsort(keys %params);

print '{ parameter ', join(', ', map { $_ = "$_=$params{$_}" } @keys ), "; }\n";

save as, e.g., change-params.pl, make executable with chmod +x, and run like:

$ ./change-params.pl [parameter-file [strings-file]]

Example output:

$ ./change-params.pl | fmt
{ parameter S0=7'd10, S1=7'd5, S2=7'd30, S3=7'd3, S4=7'd4, S5=7'd5,
S6=7'd6, S7=7'd7, S8=7'd8, S9=7'd9, S10=7'd10, S11=7'd11, S12=7'd12,
S13=7'd13, S14=7'd14, S15=7'd15, S16=7'd16, S17=7'd17, S18=7'd18,
S19=7'd19, S20=7'd20, S21=7'd21, S22=7'd22, S23=7'd23, S24=7'd24,
S25=7'd25, S26=7'd26, S27=7'd27, S28=7'd28, S29=7'd29, S30=7'd30,
S31=7'd31, S32=7'd32, S33=7'd33, S34=7'd34, S35=7'd35; }

(Note: my strings.txt contains only the 3 values you mentioned, so it only changes S0, S1, and S2. All other values in parameters are unchanged)

This constructs a hash (%params) to contain all the values in the parameters file. Then it reads in a new set of values for each element of %params from the the "strings" file. Finally, it prints the %params hash (in the same format that it was read in) in natural-sorted order.

The files to read can be specified on the command line (as arguments 1 and 2). They default to params.txt and strings.txt.

The script assumes that the strings file has one updated value per line. If it is white-space or comma-separated instead, you can split each input line into an array and iterate over that, similar to the code used to read the parameters file. You would have to keep track of the field count as each field is used, rather than the line count used above.

The script does not wrap long lines because that can easily be achieved with tools like fmt or par. e.g. ./change-params.pl | fmt as I used above.

3
  • thanks for your help, the perl script is useful to me. the code is so clean and readable , I'll get more exercise to use perl to solve other problem! thx! Commented Jan 23, 2018 at 13:36
  • glad it was of use, i try to help people learn something useful rather than just give a magic fix that they don't understand. BTW, unless you have other reasons for processing the parameters file, your "strings" file replaces every value in the parameters, so there's not really any need to read in the parameters file - just read in the strings file and print out the new parameters in the right format. i.e. the script would work exactly the same with everything from # read in the parameters file. to close(PARAMS); deleted.
    – cas
    Commented Jan 23, 2018 at 13:59
  • i got it, I'll try it. actually, I'm a fourth grader, in my undergraduate research need to use some tools in linux os, and I need to make some analysis with a circuit performed in verilog file format, so I recently try to learn some tool likes sed, awk, grep and shell script to help me solve some string processing problem. ur solution really help me a lot, thx ! Commented Jan 23, 2018 at 14:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .