Replace a character in a section of a string in Bash

114 Views Asked by At

I'm trying to replace - and : with ? only in the middle(second) section delimited by ___ (3 underscore)

input:

aaa___bb-bb:bbb___cc-cc:ccc
d-d___d-ddd:d-d___e-e:e

output:

aaa___bb?bb?bbb___cc-cc:ccc
d-d___d?ddd?d?d___e-e:e

I tried below sed command but it only replaces the last occurrence of the -: in the middle section

echo "aaa___bb-bb:bbb___cc-cc:ccc
d-d___d-ddd:d-d___e-e:e" | sed "s|\(___[^_]*\)[-:]\([^_]*___\)|\1?\2|g"

Output:

aaa___bb-bb?bbb___cc-cc:ccc
d-d___d-ddd:d?d___e-e:e

I'm not restricted to only use sed. awk, tr, etc are fine too.

3

There are 3 best solutions below

1
On BEST ANSWER

In pure native bash, with no external utilities:

in='aaa___bb-bb:bbb___cc-cc:ccc
d-d___d-ddd:d-d___e-e:e'

while IFS= read -r line; do
   first=${line%%___*}
   last=${line##*___}
   middle=${line#*___}; middle=${middle%___*}
   printf '%s\n' "${first}___${middle//[-:]/?}___${last}"
done <<<"$in"
0
On

You were close with sed solution

sed -r ':a; s/(___.*)[-:](.*___)/\1?\2/; ta' file

conditional branching is what you needed only

3
On

Try:

awk -F"___" '{gsub(/[-:]/,"?",$2)}1' OFS="___"