-2

UPDATE:

  1. The REAL answer to this MULTILINE question was given here by Stephane https://unix.stackexchange.com/a/521560/354415
  2. Alternatively go line by line with perl by Terdon below: https://unix.stackexchange.com/a/521512/354415
  3. Alternatively go line by line with IFS by myself here: https://unix.stackexchange.com/a/521550/354415

Here is my new toy:

Problem is that I want it to match only on lines which do not have the #\s* in front of the parameter.

Please do not provide alternative code e.g. sed etc. use perl

perl -we 'my $file= "parameter=9
# parameter=10
parameter=10
"; $file=~ s/.*((?<!^# ))parameter\s*=.*/parameter=replaced/g; print(":$file:\n")'

Expected output

parameter=replaced
# parameter=10
parameter=replaced

PS if you are interested to see how I progressed with this, look here:Perl Negative Lookbehind with variable length bypass maybe?

  • What is your expected output? – Inian May 28 at 12:48
  • root@ns1:~# ./test.sh parameter=replaced # parameter=10 parameter=replaced – conanDrum May 28 at 12:48
  • Basically it should not replace the second parameter which has a hash and space in front. – conanDrum May 28 at 12:49
  • 1
    "Please do not provide alternative code." Why not? Your code is not very clear or efficient. For example, you are creating 3 useless variables instead of using the existing $ARGV[N] ones and you have needless parentheses around your print call. – terdon May 28 at 12:58
  • Its only for readability.. You are free to modify, but keep the original idea intact. i.e. INPUT VARS > perl > OUTPUT VAR. Thank you. What I meant by altrnatives is about solutions in other languages and methods. This has to be kept inline with a project that requires perl regex – conanDrum May 28 at 13:08
0

This is complicated by your choice to pass the multi-line string as a single variable. it is much easier to just convert that to an array so you can use the s/// operator in its simplest form. Try this: You said you're not interested in code improvements, but to help future users, here's a simplified version of what you wrote which also avoids the bad practice of using ALLCAPS for non-environment variables:

newparameter='parameter=replaced'
filesection='
   parameter=9
# parameter=10
parameter=10
'

matchparamperl='^([^#]*)parameter\s*=.*'

sectionfixed=$( perl -le '
                         @lines=split(/\n/,$ARGV[0]);
                         s/$ARGV[1]/$1$ARGV[2]/g for @lines; 
                         print join "\n", @lines
                         ' "$filesection" "$matchparamperl" "$newparameter") 
echo "$sectionfixed"

That will return:

$ echo "$sectionfixed"

   parameter=replaced
# parameter=10
parameter=replaced

Alternatively, a little shorter:

sectionfixed=$( perl -le '
                         do{
                            s/$ARGV[1]/$1$ARGV[2]/g; print
                         } for split(/\n/,$ARGV[0])
                         ' "$filesection" "$matchparamperl" "$newparameter")
  • thanks for taking the time. Your answer is better than mine, because yours allows for any number of spaces and any number of # before the parameter to be disregarded. However, as you rightly mention, it is NOT using the multiline string and has to go line by line. My question was for multiline in order to investigate solutions. I would like to invite you then to something more relevant here: unix.stackexchange.com/questions/521523/… where this answer is more appropriate. – conanDrum May 28 at 16:36
  • @conanDrum you can do it with a multiline string but that's just making your life harder and your code less clear for no good reason. – terdon May 28 at 17:07
  • I agree, but this was the point of the question. to see what can be done with multiline. And this answers it. nothing much in the way of what was requested. It has to be done line by line. Having said that, the only answer that answered the question regarding multiline was Negative Lookbehind, i think you will aggree. – conanDrum May 28 at 17:13
  • I already mentioned you in the other thread. unfortunately I cannot upvote anything yet. – conanDrum May 28 at 17:16
  • 2
    @conanDrum that's a completely different issue. And it will depend on how you want this information to be shown. Please post a separate question if you need help with that. But here's a starter: sectionfixed=$( perl -le '@lines=split(/\n/,$ARGV[0]); $k+=s/$ARGV[1]/$1$ARGV[2]/g for @lines; print join "\n", @lines; print STDERR "$k substitutions made\n";' "$filesection" "$matchparamperl" "$newparameter"). Of course, it doesn't make much sense if you insist on mixing perl and the shell as you have requested. – terdon May 28 at 19:18
0
perl -we 'my $file= "parameter=9
# parameter=10
parameter=10
"; $file=~ s/.*((?<!# ))parameter\s*=.*/parameter=replaced/g; print(":$file:\n")'

This is how its done )))

Output:

parameter=replaced
# parameter=10
parameter=replaced

Called Negative Lookbehind http://www.blackwasp.co.uk/RegexLookahead.aspx

Thanks to Kusalananda for providing the idea.

I would never have thought of it.

  • That isn't the output you asked for. The empty line and the leading space from the first line have been removed. And yu have ignored your own requirement to go INPUT VARS > perl > OUTPUT VAR. – terdon May 28 at 13:43
  • based on -2 points on the question, and your own complaint, I decided to make things simpler. So now the point is this: unix.stackexchange.com/questions/521523/… maybe you can help? – conanDrum May 28 at 14:02
  • And yes, when I simplified the code, I forgot to change the expected output )) I will do it now. – conanDrum May 28 at 14:06
0
contents='
   parameter=9
# parameter=10
parameter=10
'

sed '/^#/!s/parameter[[:blank:]]*=.*/parameter=replaced/' <<<"$contents"

Output:

   parameter=replaced
# parameter=10
parameter=replaced

The sed code is simply applying the substitution to all lines not starting with a # character.

  • No thanks.. The task has to be done with the code provided. Only the regex must be manipulated. – conanDrum May 28 at 12:52
  • 2
    @conanDrum then please edit your question and make that clear so we don't waste your time, or ours, with solutions that won't work for you. And why can't we fix your perl code? There are a few odd choices you've made there and the syntax is more complicated than it needs to be. – terdon May 28 at 12:53
  • thanks done it. – conanDrum May 28 at 12:55
  • Not true... Only the first parameter is changed with MATCHPARAMPERL='^[^#].*parameter\s*=.*'. this is because you placed the ^ at the start and this caused it to replace only the first one. – conanDrum May 28 at 13:04
  • @conanDrum I know, that's why I removed that bit. You may want to look up "negative lookbehind assertions". – Kusalananda May 28 at 13:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.