Common Perl Regexp Idioms, translated to JavaScript

Perl idiom:
if( $x =~ m/fee(fie)foe(fum)/ ) {
  print "Yup!";
}
if( /fee(fie)foe(fum)/ . test(x) ) {
  alert("Yup!");
}

-- or, similar to the next idiom, --

if( x.match( /fee(fie)foe(fum)/ ) ) {
  alert("Yup!");
}
Perl idiom:
if( $x =~ m/fee(fie)foe(fum)/ ) {
  print "$1$2";
}
var m = x.match( /fee(fie)foe(fum)/ );
if(m) {  alert(m[1] + m[2]);  }
Perl idiom:
$x =~ s/([a-j])/X/g;
x = x.replace( /([a-j])/g , "X" );
Perl idiom:
$x =~ s/([a-j])/X$1/g;
x = x.replace( /([a-j])/g , "X$1" );
Perl idiom:
$x =~ s/([a-j])/$funky{$1}/g;
x = x.replace( /([a-j])/g ,
  function(x) { return funky[x]; } 
);
Perl idiom:
$x =~ s/([A-Z])([a-z])/thang($1,$2)/g;
x = x.replace( /([A-Z])([a-z])/g ,
  function(c) { return thang( c[0], c[1] ); } 
);
Perl idiom:
@y = ($x =~ m/([a-j]+)/g);
y = x.match( /([a-j]+)/g ) || [];
Perl idiom:
$x =~ tr/a-j/0-9/
-- or --
$y = $x =~ tr/a-j/0-9/;
// Use a regexp replacement,
// as with the "funky" example above.
Perl idiom:
while( $x =~ m/(f.)/g ) {
  print "Zonk! $1 at ", pos($x), "!\n";
}
var x = "fee fie foe fum";
var re = /(f.)/g;
while(1) {
  var m = re.exec(x);
  if(!m) break;
  print("Zonk! " + m[1] + " at " +
   re.lastIndex.toString() + "!\n");
}
Perl idiom:
$y = quotemeta($x);
y = x.replace( /([^A-Za-z0-9])/g , "\\$1" );
Perl idiom:
$x = qr/$y/;
x = new RegExp(y);

This leads us to an interesting problem: suppose I have a hash in x, whose keys are string-values to replace, and the value for each is the string value that should be put in instead; and I want to perform replacement based on that.

var i = "the poppy is popular with pop stars?";
var map = { 'popular': 'fashionable',
  'pop': 'fun', 'poppy':'flower', "?":"!"
};

alert(super_replace(i, map));
// shows: "the flower is fashionable with fun stars!"

function super_replace (s, map) {

  var re_bits = [];
  for(var k in map) { re_bits.push(k) }
  if(!re_bits.length) return s;

  re_bits.sort( _for_re );
  for(var i = 0; i < re_bits.length; i++ ) {
    re_bits[i] = quotemeta( re_bits[i] );
  }
  var re = new RegExp( "(" +
    re_bits.join("|") + ")", 'g' );

  return s.replace( re,
   function (bit) { return map[bit] } );
}

function quotemeta (s) {
  return s.replace( /([^a-zA-Z0-9])/g, "\\$1" );
}

function _for_re (a,b) {  // longest-first
 return(
   (a.length > b.length) ? -1
 : (a.length < b.length) ?  1
 : (a < b) ? -1
 : (a > b) ?  1
 : 0
 );
}
That super_replace function is handy -- notably, most uses of tr/// are just a special case of it.

Sean M. Burke, 02008-02-06