Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a regex in JavaScript to match $ variable prefix syntax (like found in Bash scripts)

I'm trying to write a regular expression in JavaScript to search a multi-line bash script and extract all the variable names. I can neither seem to figure it out myself nor find a script that does exactly what I need.

I've gotten this far:

var re = /(?:^|\W)\$(\w+)(?!\w)/g;
var s = "test $test1 testagain$test2 testyetagain $test3 $test4$test5";
var matches = [];
while (match = re.exec(s)) {
  matches.push(match[1]);
}

This will give me "test1", "test3", and "test4". But I would also like to get "test2" and "test5".

It would also be great if there were a way I could get "\$" to NOT match if it appears in the string. In other words, is there a way to escape the "$" string in the text so that it is ignored by my regular expression? So in case "\$1.00" appeared in the text, it would not match "1" as the above regex does now.

Thanks in advance for any help or for pointing me in the right direction.

PS This is actually for Action Script 3 but anything that works in JavaScript pre-ES6 should work in AS 3.

PPS The final goal is to replace these matches with variables from a key-value hash.

like image 608
jpwrunyan Avatar asked Nov 28 '25 19:11

jpwrunyan


2 Answers

You could repeatedly match \$ (in which case do nothing) or $\w+ (in which case, it's an unescaped dollar sign indicating the start of a variable you want to match). Use a replacer function to decide whether to leave the match alone, or replace with whatever other string you want:

const replacements = {
  test1: 'testone',
  test2: 'testtwo',
  test3: 'testthree',
  test4: 'testfour',
  test5: 'testfive'
};
var s = "test $test1 testagain$test2 testyetagain $test3 $test4$test5 \\$1.00";
const result = s.replace(
  /\\\$|\$(\w+)/g,
  (match, g1) => match === '\\$'
    ? match // replace with the matched string - in other words, leave it unchanged
    : replacements[g1]
);
console.log(result);

On newer engines, you could negative lookbehind for a backslash instead, which makes the logic a lot easier, but it's not a good cross-browser solution, since it'll only work in new environments:

const replacements = {
  test1: 'testone',
  test2: 'testtwo',
  test3: 'testthree',
  test4: 'testfour',
  test5: 'testfive'
};
var s = "test $test1 testagain$test2 testyetagain $test3 $test4$test5 \\$1.00";
const result = s.replace(
  /(?<!\\)\$(\w+)/g,
  (_, g1) => replacements[g1]
);
console.log(result);
like image 66
CertainPerformance Avatar answered Dec 01 '25 07:12

CertainPerformance


You can use this regex

(?<!\\)\$([^\W$]+)
  • (?<!\\) - Negative lookbehind to avoid \$ to match
  • \$ - Matches $
  • ([^\W$]+) - Match anything except word non word character and $

Demo

like image 43
Code Maniac Avatar answered Dec 01 '25 07:12

Code Maniac



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!