Skydivr
Skydivr

Reputation: 1

using sed with variables to replace quoted string in bash

Working in bash. I have a file.txt with contents in the following format.

default=60.0,
default=False,
default=(0.2, 0.2, 0.3, 1.0),
default="blend",
default="/path/to/directory")

There is other info on each line before and after what i am showing but this is the part i want to edit. i am trying to replace the values following the equals sign and before the comma with values stored in a variable. i can make it work if i know all the info of line number, what to replace, and what replacing with beforehand but as soon as i start working with variables it all falls apart. i can use sed -i '4s/default="blend",/default="burn",/' file.txt to replace blend with burn on line 4 but how can i do this with variables? i cant seem to find the right way to quote this. and obviously the data i am trying to replace is not consistent, some numbers, some strings, some quoted, some not, some bracketed, some not, some followed by ,, some followed by ). focused on line 4 currently, if var1=4 and var2="burn" and default= could be any of "blend, burn, or bump". so say i want to replace whatever follows default= with "burn" on line 4, var1=4 var2="burn"

Desired output:

default=60.0,
default=False,
default=(0.2, 0.2, 0.3, 1.0),
default="burn",
default="/path/to/directory")

hopefully what i am trying to accomplish makes sense because i'm stuck. how can i make this work? doesn't have to use sed if there is another simple way.

edit: contents of entire line are: parse.add_argument("-j", "--blend_type", default="blend", choices=["blend", "burn", "bump"], help="type of blend the shader can do")

using: sed -r "$var1{s/(default=\")(.*)(\".*$)/\1$var2\3/p}" file.txt

my output is parse.add_argument("-j", "--blend_type", default="burn")

and i want it to be parse.add_argument("-j", "--blend_type", default="burn", choices=["blend", "burn", "bump"], help="type of blend the shader can do")

i'm close but can't seem to keep the end of the line intact.

Upvotes: 0

Views: 205

Answers (3)

KamilCuk
KamilCuk

Reputation: 140880

i can use sed -i '4s/default="blend",/default="burn",/' file.txt to replace blend with burn on line 4 but how can i do this with variables?

linenumber=4
from=blend
to=burn

# a bit extra: escape special characters
# https://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern
from=$(printf '%s\n' "$from" | sed -e 's/[]\/$*.^[]/\\&/g');
to=$(printf '%s\n' "$to" | sed -e 's/[\/&]/\\&/g')

# Note the quoting
sed -i "${line}s/default=\"${from}\",/default=\"${to}\",/"
#        ^^^^^^                                            - used ${line} so that 's' is separate
#                        ^^       ^^          ^^     ^^    - double quotes within double quoting need to be escaped
#      ^                                                 ^ - double quotes so that ${..} are expanded
sed -i '"$var1"s/default="blend",/default="burn",/' $f2

Variables are not expanded within single quotes.

sed -i "$var1"s/default="*"/default="$var2"/ file.txt

Regex is not glob. "* matches zero or more " characters. It does not match anything, * matches zero or more of preceding character or group. A dot . matches anything, so you could default=".*" or better I would go with default="[^"]*".

sed -i ""$var1"s/default="*",/default="$var2",/" file.txt

Use an editor with syntax highlighting. Even stackoverflow syntax highlighting should hint you - " close the other ". To write " within double quotation, escape them "\"".

Upvotes: 1

Raman Sailopal
Raman Sailopal

Reputation: 12867

To expand the variables, place the sed statement in double quotes as opposed to single quotes. Also since you are using var1 to hold the line to process, place the proceeding substitution statement in {}:

sed -r "$var1{s/(^default=\")(.*)(\",?.*$)/\1$var2\3/}" file1.txt

Also, enable the regular expression interpretation with -r or -E and then split the line into three sections specified in parenthesis and substitute the line for the first section, var2 and then then the third section. Escape any double quotes in the text to change where required.

Upvotes: 0

markp-fuso
markp-fuso

Reputation: 33914

Assumptions/provisos:

  • patterns to be searched and replaced can contain any printable characters which means ...
  • said patterns may need to include escape characters to keep from clashing with sed delimters and constructs
  • default=<search_pattern> only shows up once in a line

Sample data:

$ cat file.txt
abcde default=60.0, ABC
12345 default=False, ABC
STUVW default=(0.2, 0.2, 0.3, 1.0), ABC
@#%#@ default="blend", ABC
ABCDE default="/path/to/directory") ABC

One sed idea based on 2 variables (var1 == search / var2 == replacement):

sed -E "s/default=$var1/default=$var2/g" file.txt

Test case #1:

var1='"blend"'
var2='"burn"'
sed -E "s/default=$var1/default=$var2/g" "${infile}"

Generates:

abcde default=60.0, ABC
12345 default=False, ABC
STUVW default=(0.2, 0.2, 0.3, 1.0), ABC
@#%#@ default="burn", ABC                              # modified line
ABCDE default="/path/to/directory") ABC

Test case #2:

var1='\(0.2, 0.2, 0.3, 1.0\)'                          # must escape the parens
var2='[something different = 3.22]'
sed -E "s/default=$var1/default=$var2/g" "${infile}"

Generates:

abcde default=60.0, ABC
12345 default=False, ABC
STUVW default=[something different = 3.22], ABC        # modified line
@#%#@ default="blend", ABC
ABCDE default="/path/to/directory") ABC

Test case #3:

var1='"\/path\/to\/directory"'                         # must escape the forward slashes
var2='"\/a\/new\/directory"'                           # must escape the forward slashes
sed -E "s/default=$var1/default=$var2/g" "${infile}"

Generates:

abcde default=60.0, ABC
12345 default=False, ABC
STUVW default=(0.2, 0.2, 0.3, 1.0), ABC
@#%#@ default="blend", ABC
ABCDE default="/a/new/directory") ABC                  # modified line

Upvotes: 0

Related Questions