Use COUNTW().
First let's convert your listing into an actual dataset.
data have;
input ID Var1 :$40. Var1Count :$20.;
cards4;
1 abc;bde;cf 1;2;5
2 x;yz 3;1
3 a;x 2;7
4 cf;bdx;yz 6;3;2
5 . .
6 x 1
7 abc 3
8 xz;adk 2;8
9 a 3
10 bc;bd 2;1
;;;;
You will need to decide how long to make the NEW var1 variable. For this example let's set the old one to length $40 and the new on to $20. Let's make the new count variable numeric instead of character.
Now just use a DO loop to output each pair of values.
data want;
set have;
length _var1 $20 count 8 ;
do index=1 to countw(var1,';');
_var1 = scan(var1,index,';');
count = input(scan(var1count,index,';'),32.);
output;
end;
keep id _var1 count;
rename _var1=Var1 count=Var1Count ;
run;
Result
![Tom_0-1723826079980.png Tom_0-1723826079980.png](https://communities.sas.com/t5/image/serverpage/image-id/99366iAB540B1F07C2827C/image-size/medium?v=v2&px=400)
If your original string actually have those extra spaces after the semicolons then you will probably want to add in a LEFT() function call to remove them.
_var1 = left(scan(var1,index,';'));
You might want to also keep the INDEX variable so you know the original order the values were in inside the character strings.