Home > Back-end >  find & replace only exact match between delimiters in string values
find & replace only exact match between delimiters in string values

Time:01-25

I have a string value stored in a variable:

PTYPE="Other Farm|Raised Ranch|Farm house|Other|A-Frame|Log Home"

I want to find & replace Other with some value like NOTHING. All values are stored in variables.

WhatToChange=Other
NewValue=NOTHING

echo $PTYPE|sed -e "s@${WhatToChange}@${NewValue}@g"

This is replacing all the occurances of Other and getting output like:

NOTHING Farm|Raised Ranch|Farm house|NOTHING|A-Frame|Log Home

Is there any way I can exactly change only the exact one? The place for ${WhatToChange} is variable.

CodePudding user response:

To match either the exact character | or the beginning of the line, use ([|]|^).

To match either the exact character | or the end of the line, use ([|]|$).

To put a | back in place only when appropriate, store these in match groups, and refer to those groups with \1 or \2:

PTYPE="Other Farm|Raised Ranch|Farm house|Other|A-Frame|Log Home"
WhatToChange=Other
NewValue=NOTHING

sed -re "s@(^|[|])${WhatToChange}($|[|])@\1${NewValue}\2@g" <<<"$PTYPE"

...emits as output:

Other Farm|Raised Ranch|Farm house|NOTHING|A-Frame|Log Home

...and still works even if WhatToChange is matched at the beginning or end of the list.

CodePudding user response:

As you have well defined fields and want an exact match, awk could be easier to use than sed; at the very least, you won't have to worry about escaping the strings for using it in the sed expression:

echo "Other Farm|Raised Ranch|Farm house|Other|A-Frame|Log Home" |
awk -v old="Other" -v new="NOTHING" \
    'BEGIN {FS = OFS = "|"} {for(i=1;i<=NF;i  ) if($i == old) $i = new} 1'

output:

Other Farm|Raised Ranch|Farm house|NOTHING|A-Frame|Log Home

CodePudding user response:

For fun, some perl:

This is like @Charles's sed solution: Note the \Q...\E so that the "to change" value is treated as literal text.

echo "$PTYPE" | perl -spe '
    s{ (?:^|\|)\K \Q$WhatToChange\E (?=\||$) }{$NewValue}gx
' -- -WhatToChange=Other -NewValue=NOTHING

This is like @Fravadona's awk solution:

echo "$PTYPE" | perl -F'[|]' -sane '
    print join "|", map {$_ eq $WhatToChange ? $NewValue : $_} @F
' -- -WhatToChange=Other -NewValue=NOTHING
  •  Tags:  
  • Related