1

I've got a line with an identifier, then a pattern (in my case, a semicolon) and then a list of numbers:

echo "sp16;111111111111111111111111111111211" 

I'd like to insert a semicolon between all numbers as in (desired output):

echo "sp16;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;2;1;1"

So far, I found how to insert a semicolon between all characters using sed:

sed 's/.\{1\}/&;/g'

But, then it also inserts semicolons before matching the first semicolon and also it adds a semicolon ad the end of the line.

toolic
  • 57,801
  • 17
  • 75
  • 117
MrLungo
  • 33
  • 4

6 Answers6

5

With a Perl's one-liner:

perl -pe 's/^([^;]+;)([0-9]+)/$1 . join ";", split "", $2/e' file

sp16;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;2;1;1

The regular expression matches as follows:

Node Explanation
^ the beginning of the string anchor
( group and capture to \1:
[^;]+ any character except: ; (1 or more times (matching the most amount possible))
; ;
) end of \1
( group and capture to \2:
[0-9]+ any character of: '0' to '9' (1 or more times (matching the most amount possible))
) end of \2

Perl's code explanations

Operator Meaning
$1 captured group 1 like \1 in sed
. concatenation
join ";", join with the character ';' the following list...
split "", $2 split captured group $2 or \2 in a list of digits
e modifier that allow Perl's code/expression in the right part of substitution s///
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
1

With GNU sed:

echo "sp16;111111111111111111111111111111211" \
  | sed -E ':a; s/(;[^;])([^;]+)$/\1;\2/; ta'

Output:

sp16;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;2;1;1

See: man sed and The Stack Overflow Regular Expressions FAQ

Cyrus
  • 84,225
  • 14
  • 89
  • 153
0

Using any awk:

$ echo "sp16;111111111111111111111111111111211" |
    awk 'BEGIN{FS=OFS=";"} {gsub(/./,FS"&",$2); sub(FS,"")} 1'
sp16;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;2;1;1
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

Here is another sed command that will work for any sed version:

sed -E -e :a -e 's/([0-9])([0-9]+)$/\1;\2/; ta' file

sp16;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;2;1;1

Here is a suggested awk solution:

awk -F';' -v OFS= '{gsub(/./, FS "&", $2)} 1' file

sp16;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;2;1;1
anubhava
  • 761,203
  • 64
  • 569
  • 643
0

This might work for you (GNU sed):

sed 's/;/\n/;h;s/\B/;/g;H;x;s/\n.*\n/;/' file

Divide and conquer.

Replace the first delimiter ;, by a newline and make a copy.

Insert a ; between each in-word character.

Append the result to original copy.

Replace everything between the two introduced newlines by ;.


If the first identifier is always 4 characters:

sed 's/./;&/7g' file
potong
  • 55,640
  • 6
  • 51
  • 83
0
echo "sp16;111111111111111111111111111111211" | 

mawk 'gsub(".", ";&", $NF)' OFS= FS=';' 

sp16;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;2;1;1
RARE Kpop Manifesto
  • 2,453
  • 3
  • 11