I have a setting file states 1,2,3 meaning to place a , after the 1st, 2nd, and 3rd byte.
For example my input is
stackoverflow
then I want to make it
s,t,a,ckoverflow
How should I do it with Linux tools? I feel sed should be used, but I don't know how to do it.
Edit:
I have more than 10 commas to be placed. And the line also includes multi-byte characters.
In sed:
echo stackoverflow | sed 's/./&,/1;s/./&,/3;s/./&,/5'
s/.../.../n replaces the nth match. After the first replacement, the second byte would now be the third match, and after that, the third byte would now be the fifth.
Or, with regex groups:
echo stackoverflow | sed 's/\(.\)\(.\)\(.\)/\1,\2,\3,/'
In Basic Regular Expressions (BRE), \(…\) is used to group expressions. You can refer to the text that matched the nth group using \n, to re-use matched text in the replacement, for example. So, in this case, I have three groups, each containing just ..
With GNU sed, you can avoid the \ by using Extended Regular Expressions (ERE):
echo stackoverflow | sed -r 's/(.)(.)(.)/\1,\2,\3,/'
With multibyte charsets, try with the C locale:
$ echo 'æ ' | LC_ALL=C sed 's/\(.\)\(.\)\(.\)/\1,\2,\3,/'
�,�, ,
$ echo → | LC_ALL=C sed 's/\(.\)\(.\)\(.\)/\1,\2,\3,/'
�,�,�,
IFS=, read -ra arr <<< "$1"
rules=()
for i in "${arr[@]}"; do
rules[$i]=1
done
s=stackoverflow
for (( i=0; i<${#s}; i++ )); do
if (( ${rules[i+1]} )); then
printf '%s,' "${s:i:1}"
else
printf '%s' "${s:i:1}"
fi
done
Usage example:
$ ./sof 1,2,3
$ s,t,a,ckoverflow
$ ./sof 1,2,3,7
$ s,t,a,ckov,erflow
This might work for you (GNU sed):
sed 's/\B/\n/g;s/\n//4g;s/\n/,/g' file
or:
sed 's/\B/,/;s/\B/,/;s/\B/,/' file