Better for a future maintainer of the JSL, or better for the computer, or some other measure? Here's a couple of ideas; I lean towards the first one, partly because I imagine you started with a JSL expression, not a text string.
A note about comments and seeing trees vs seeing forests: my comments are tree-level. They don't describe your goal (the forest), they describe the trees. Anyone maintaining your JSL in the future will want both kinds. A forest level comment should explain why you are thinking about these values. The tree level is about how a non-obvious bit of code works.
ex = "Select Where( :\!"BWA\!"n == \!"BWA005\!" | :\!"BWA\!"n == \!"BWAZ006\!" )";
// write(ex) // Select Where( :"BWA"n == "BWA005" | :"BWA"n == "BWAZ006" )
// Regex match( ex, "[\!"](BWA|BWAZ|BWAZ_)([0-9]{1,})(.*?)[\!"]" )
// desired result: "BWA005,BWAZ006"
//
// it isn't 100% clear what the rules are. These examples make different assumptions.
// assume the text is valid JSL that can be parsed back into an expression
// below, also assumes | but not & and no nested parens
expression = Parse( ex ); // Select Where( :BWA == "BWA005" | :BWA == "BWAZ006" )
// get the argument of the select where(...)
expression = Arg( expression, 1 ); // :BWA == "BWA005" | :BWA == "BWAZ006"
// assume there are only | (or) operators, change x|y|z => {x,y,z}
Substitute Into( expression, Expr( Or() ), {} ); // {:BWA == "BWA005", :BWA == "BWAZ006"}
result = {}; // accumulate answer in a result list
// process the expression list
For Each( {op}, expression, // :BWA == "BWA005" etc.
// the Right Hand Side of :BWA == "BWA005" is "BWA005"
RHS = Arg( Name Expr( op ), 2 ); // assign(:BWA,"BWA005"), want 2nd arg
// apply the test to see if this is one to keep
If( !Is Missing( Regex( RHS, "(BWA|BWAZ|BWAZ_)([0-9]+)" ) ),
Insert Into( result, Arg( op, 2 ) ); // yes: keep it in the result list
);
);
// join the list of RHS strings, separated by commas
Show( Concat Items( result, "," ) ); // Concat Items(result, ",") = "BWA005,BWAZ006";
// alternate example
// assume the strings can't collide with column names, perhaps because no
// column name has a suffix number and all strings do have a suffix number
result = {};
Pat Match(
ex,
// this is the pattern; it repeats as long as it can
Pat Repeat(
// either match the BWA... pattern, in quotes, stashing the regex match into the result:
( "\!"" + Pat Regex( "(BWA|BWAZ|BWAZ_)([0-9]+)" ) >> result[N Items( result ) + 1] + "\!"" )
// >> is the patImmediate() operator that copies the LHS match into the RHS location
// the list is initially 0 items long, and [nitems+1] extends the list by one more item
| // OR the alternative...
Pat Len( 1 ) // advance one character. This is how most of the text is matched.
)
);
Show( Concat Items( result, "," ) ); // Concat Items(result, ",") = "BWA005,BWAZ006";
// you *could* write a pattern match that would parse the text as an expression,
// but that is what the first example did.
Craige