Search and replace shell variable with multiline s

2019-06-12 12:26发布

I know there are lots of similar questions but, I guess because of the formatting of the search/replace variables they are not working for my situation.

The overall script I am working on will read a text file (using combinations of grep and awk) to create two shell variables, $find and $replace. $find is a single line string containing all manner of characters. $replace is a multiline string containing all manner of characters.

example:

echo "$find"

returns

type result input1 another_input random_input<10> / name

and

echo "$replace"

returns

.TAG name
result input1 random_input / name1
random_input<10> input1 another_input / name2
.NTAG

Now I just need to substitute $find with $replace. I have tried sed and perl but it fails.

Tried (among a lot of other stuff)

perl -e -i.bak "s/$find/$replace/g" text.file
perl -e -i.bak 's,"'$find'","'$replace'",g' text.file
perl -e -i.bak "s|$find|$replace|g" text.file

and

sed -i "s/$find/$replace/g" text.file

My guess is the problems are caused by some character in the string being interpreted as special characters.

Any help is appreciated!

3条回答
贪生不怕死
2楼-- · 2019-06-12 12:42

This will work for any values of find or replace:

$ cat file
foo
type result input1 another_input random_input<10> / name
bar

$ awk -v find="$find" -v replace="$replace" 's=index($0,find){$0=substr($0,1,s-1) replace substr($0,s+length(find))}1' file
foo
.TAG name
result input1 random_input / name1
random_input<10> input1 another_input / name2
.NTAG
bar

if find is always one whole line it can be simplified, e.g. this might be all you need:

$ awk -v find="$find" -v replace="$replace" '$0==find{$0=replace}1' file
foo
.TAG name
result input1 random_input / name1
random_input<10> input1 another_input / name2
.NTAG
bar
查看更多
爷、活的狠高调
3楼-- · 2019-06-12 12:50

one way with sed, quick and dirty so not bullet proof like the awk of @Ed Morton

find_sed="$( printf "%s" "${find}" | sed 's/[^0-9(){}]/\\&/g' )"
replace_sed="$( printf "%s" "${replace}" | sed "s/[&\\]/\\/g;s/\n/\\&/g' )"

sed "s/${find_sed}/${replace_sed}/g" YourFile
  • Could be a one line with internal substitution instead of variable, but more explicit like this
  • posix version ( --posix with GNU sed), if not posix, adapt [^0-9(){}] depending your special character that use a escape char for special meaning like \+\n\d\
查看更多
Deceive 欺骗
4楼-- · 2019-06-12 12:55

restructure your variable to read

replace=".TAG name\nresult input1 random_input / name1\nrandom_input<10> input1 another_input / name2\n.NTAG"

or restructure it like this

replace='.TAG name\
    result input1 random_input / name1\
    random_input<10> input1 another_input / name2\
    .NTAG'

Also your delimiter is causing conflict with your variable replace characters since there are / in your variable

you can try # as your delimiter or any other char that is not in your variable

 sed "s#$find#$replace#g" text_file
查看更多
登录 后发表回答