1

I have a file like this:

data data data
$globaltext blah gibberjabber
somemorestuff etc
);
data data data
$otherjunk yada gibberish
etc etc
more etc
);

My desired result is this file:

data data data
/*$globaltext blah gibberjabber
somemorestuff etc
);*/
data data data
/*$otherjunk yada gibberish
etc etc
more etc
);*/

I know how to do it using a for loop with sed, but I'd like a 1-line sed command to achieve that, Something like:

sed '/blah\|yada/s/^\(\$.*)\;\)/\/\*\1\*\//' filename

The pattern match at the beginning limits the search to 1 line, so obviously the above command fails. But the concept is what I want:

  1. Match any of a list of patterns (blah or yada),
  2. then add desired text (/*) to beginning of the matched line,
  3. AND add other desired text (*/) to the end of the next line matching a different pattern ();) where the # of lines between the 2 matches varies (its not always 2 lines apart etc)

Is that possible or should I use for loop or a better method?

Mostly asking to learn, since I'm new to shell scripting.

  • my suggestion would be to use multiple -e parameters -- one for blah|yada and the other for ); – Jeff Schaller Jan 4 '16 at 15:43
  • yes to both. only edit if line containing blah or yada begin w/ $. & all edited portions end w/ ); – mowglie Jan 5 '16 at 19:56
2
sed   -e's|^\$|/*&|;t$' -eb -e:$      -e'### handle top end of loop' \
      -e's|);$|&*/|;t'  -en -eb$      -e'### handle the bottom end'

data data data
/*$globaltext blah gibberjabber
somemorestuff etc
);*/
data data data
/*$otherjunk yada gibberish
etc etc
more etc
);*/

Both attempted s///ubstitutions are tested. In the first case, if the substitution is successful, sed will not wind up branching out of the script and will branch instead to the :$ label. When it is not successful, it doesn't jump the branch command and so it just branches away and autoprints input until ^\$ is matched.

Once it does match it enters a closed loop beginning at :$ and ending at b$ and so it doesn't try the first s///ubstitution again until the loop completes. In this end of the loop sed tests the );$ match case for a successful s///ubstitution, and, once it is successful, it branches out of the script to restart the cycle from the top all over again with the next input line, if any. Until it does it will recursively auto-print then over-write pattern space with the next input line for each iteration - and so it never needlessly buffers.

  • did you mean /* for the top end sed line? based on my sample file, i want /* but i'm not sure if you some code related reason to use */ in both lines. – mowglie Jan 7 '16 at 0:37
  • i didnt know sed could test/fail! i dont know anything about branching so i will read up on that. what do :$ and b$ label mean? are those the ways one defines beg/end of a branch loop? – mowglie Jan 7 '16 at 0:42
  • lastly, the -e option is problematic b/c i use the -i option so that the 1 liner edits the file directly vs redirect output to file, cat into existing file, rm output file etc. anyway to use the -i option still? perhaps separate the sub portions with ; to execute one after the other? though not sure if this eliminates branching/looping. thanx! – mowglie Jan 7 '16 at 0:44
  • @mowglie - what do you mean problematic? yeah, you can use the -i option but i don't recommend it - it's pretty insecure. but what does -i have to do with -e? – mikeserv Jan 7 '16 at 0:53
  • @mowglie - sorry about the backwards comment thing. there's no reason for that - i was just dumb. – mikeserv Jan 7 '16 at 0:54

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.