leigon
leigon

Reputation: 47

Use sed to change first occurrence after match

I have worked out the syntax to get sed to replace after the match, but it replaces all instances following the match. Can someone please tell me what I'm doing wrong here. I know it's something minor but I can't seem to get it to take.

sed -e "0,/\#NOTE/!  s/$NEW_VVER/$CURRENT_VER/" FILE1 > FILE2

I have also tried

sed -e "0,/\#NOTE/!  s/$NEW_VVER/$CURRENT_VER/1" FILE1 > FILE2

Here is the full line with the sed commands and the data it is to change.

sed -e "0,/\#NOTE/!  s/$NEW_VVER/$CURRENT_VER/" -e "0,/\#NOTE/!  s/$NEW_VER/$VER/" -e "0,/\#NOTE/!  s/$EVEN_LENGTH/$OLD_EVEN_LENGTH/" -e "0,/\#NOTE/!  s/$ODD_LENGTH/$OLD_ODD_LENGTH/" -e "0,/\#NOTE/!  s/$START_DIGIT/$OLD_START_DIGIT/" -e "0,/\#NOTE/!  s/$STRING/$OLD_STRING/ FILE1 > FILE2"

Basically it should find the string "#NOTE" and replace only the first instance following the match.

    #CHANGE THESE EVERY VERSION
#NOTE: Don't forget to add the needed variables to the version arguments. 
   DEFAULT_VERSION = REPVVER
   EVEN_LENGTH = REPELENGTH 
   ODD_LENGTH = REPOLENGTH  
   CURR_VERSION = "REPVVER"
   START_DIGIT = REPSTARTDIGIT
###########################################

for example it should find the string "#NOTE" and replace the "REPVVER" string with a new value. But it will replace not only that one but all following.

Upvotes: 2

Views: 6175

Answers (2)

NeronLeVelu
NeronLeVelu

Reputation: 10039

sed -e '/#NOTE/!b' -e ':a' -e "s/$NEW_VVER/$CURRENT_VER/;t trail" -e 'n;ba' -e ':trail' -e 'n;btrail' FILE1 > FILE2
  • posix compliant and oneliner (replace all ' -e ' with a new line for a multiline script (also " and replace surrounding 'by " for variable interpretation )
  • change the first occurence of NEW_VVER after #NOTE but not on same line (assumming # note is a comment line). Linne could be 50th after #NOTE
  • Assuming content of NEW_VVER and CURRENT_VER are regex compliant (escaping meta char like &)

Upvotes: 7

John Bollinger
John Bollinger

Reputation: 180058

Here's a relatively rough way to do it:

sed -e "/\#NOTE/,/./  s/$NEW_VVER/$CURRENT_VER/" FILE1 > FILE2

That limits the substitution to the line containing #NOTE and the next line. It will be performed at most once in each line.

This approach assumes that the substitution will change nothing on the #NOTE line. That assumption holds for your example data, but you'll have to decide whether it is acceptable in general.

Update:

If the line in which to perform the substitution does not immediately follow the #NOTE line, and if you can depend on the value of $NEW_VVER to not contain any regex metacharacters, then you can do it with this variation on the above:

sed -e "/\#NOTE/,/$NEW_VVER/  s/$NEW_VVER/$CURRENT_VER/" FILE1 > FILE2

In that case, the range of lines to which the substitution applies starts with one matching /\#NOTE/, and ends with the next one matching /$NEW_VVER/. As above, this assumes that the substitution will change nothing in the /\#NOTE/ line.

Upvotes: 2

Related Questions