use Regexp::Common qw/balanced/; while () { chomp; my $bp = qr/$RE{balanced}{-parens=>'()'}{-keep}/; $_ =~ s{ &? # optional & ( # capture either: (?<=&) \w+ # bareword preceeded by & | # or \w+ (?=\s*\() # bareword followed by ( ) # (?: \s* (?=\())? # optional white space, if followed by ( (?: # either: $bp # balanced parens | # or # nothing! ) } # if no second capture, supply an empty () { $1 . ($2 || '()') }exg; print "$_\n"; } __DATA__ &foobar &foobar() foobar() &foobar("asdf") &foobar( test(), qw(etc.)) &foobar( test(test() . test()) ) &foobar("a", 5, qw(dave jen anne matt), map({tr/[a-z]/[A-Z]/; $_;} @mixedCase)); &dont_change if not &function() &foobar ('<- white space?') &foobar( &test_nested )