in reply to split on delimiter unless escaped

That's not splitting what you do. You're also replacing escaped escapes with the escape (it seems you're replacing every !! with !). You cannot do that with just a split, you'll have to parse. I think this does what you want:
#!/usr/bin/perl use 5.010; use strict; use warnings; while (<DATA>) { chomp; my @a; my $i = 0; while (/(!.|.)/g) { my $char = $1; if ($char eq ";") { $i++; next; } $char = $1 if $char =~ /!(.)/; $a[$i] .= $char; } say "@a"; } __DATA__ foo;bar foo!;bar;baz foo!!;bar!;baz;qux foo!!!;bar!!;baz!;qux;quux foo!!!!;bar!!!;baz!!;qux!;quux;garply foo!!!!!;bar!!!!;baz!!!;qux!!;quux!;garply;waldo
Output:
foo bar foo;bar baz foo! bar;baz qux foo!;bar! baz;qux quux foo!! bar!;baz! qux;quux garply foo!!;bar!! baz!;qux! quux;garply waldo