Reputation: 1
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
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
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
Reputation: 33914
Assumptions/provisos:
sed
delimters and constructsdefault=<search_pattern>
only shows up once in a lineSample 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