Reputation: 121
I want to replace character e.g. ',' with ';' only between two consecutive '[' and ']' using sed or perl linux command.
Input
abcd,e%sa,@ert&,,qet|,[,,efeg,sy bh|slhg],oiuy#,[abh,ohg;,a oiu],ayba
Ouptut
abcd,e%sa,@ert&,,qet|,[;;efeg;sy bh|slhg],oiuy#,[abh;ohg;;a oiu],ayba
I tried to create sed substitution command
echo "abcd,e%sa,@ert&,,qet|,[,,efeg,sy bh|slhg],oiuy#,[abh,ohg;,a oiu],ayba" | sed 's/\[\([^]]*\),\([^[]*\)\]/\[\1;\2\]/g'
Output
abcd,e%sa,@ert&,,qet|,[,,efeg;sy bh|slhg],oiuy#,[abh,ohg;;a oiu],ayba
but it is replacing only once in sub-string between each '[' and ']'.
What mistake I'm doing in the above sed command or any other way to do the same?
Upvotes: 2
Views: 668
Reputation: 204638
I know you said you wanted sed or perl but the code to do this would be very clear and simple in GNU awk:
$ awk -v RS='[[][^]]+]' '{gsub(/,/,";",RT); printf "%s%s", $0, RT}' file
abcd,e%sa,@ert&,,qet|,[;;efeg;sy bh|slhg],oiuy#,[abh;ohg;;a oiu],ayba
In the above you just set RS
to the regexp you want to find ([
then not ]
s then ]
), then replace ,
with ;
within the strings that match that regexp (as stored in RT
) and then print the result. No cryptic escape sequences or arcane combinations of single character runes required.
I expect a sed script that can do this will be GNU-specific, and perl is non-standard so if you have or can install either of those then you should have or be able to install GNU awk too.
Upvotes: 3
Reputation: 43199
Using Perl
, you could use
(?:\G(?!\A)|\[)[^],]*\K,
In Perl
this could be:
perl -pi.bak -e 's/(?:\G(?!\A)|\[)[^],]*\K,/;/g' test.txt
Upvotes: 3
Reputation: 23697
Modified sample input, hope my understanding of the question is correct:
$ s='a,b,c[,,1,23,4]e,w[6,7,,32]j,g'
$ echo "$s" | sed ':a s/\[\([^]]*\),\([^[]*\)\]/\[\1;\2\]/; ta'
a,b,c[;;1;23;4]e,w[6;7;;32]j,g
The sed
command above is modified from the one mentioned in the question to use a loop to replace all occurrences. You can simplify it to sed -E ':a s/(\[[^]]*),([^[]*])/\1;\2/; ta'
:a
marks a label for the substitute command. ta
will branch to label a
only if the substitution succeeds. See https://www.gnu.org/software/sed/manual/sed.html#Programming-Commands for documentation.
You can do it without loop using perl
$ echo "$s" | perl -pe 's/\[[^]]+]/$&=~tr|,|;|r/ge'
a,b,c[;;1;23;4]e,w[6;7;;32]j,g
The e
flag allows to use Perl code in replacement section. Here $&=~tr|,|;|r
will replace ,
with ;
only for the matched portion ($&
is similar to &
in sed
- gives entire matching portion)
Upvotes: 2