Match arithmetic operators in a string but not negative numbers - javascript

I would like to match arithmetic operators in a string while avoiding matching negative numbers.
For example, the string : "-5.0 + 9.34 - 6.0 * - 2.1 * 3.1 / - 2.0" would match +, -, *, *, /,, leaving the negative numbers unmatched. (even with space after the unary operator)
I've done some research and found this : ((?!^)[+*\/-](\s?-)?), but it actually matches +, -, * -, *, / -.
I am using ECMAScript regex.
More details : what I am trying to achieve is to split a string at the matches using string.split while not removing the separator.
for example : ([+\-*\/%]) does match every operators and doesn't remove them in a string.split scenario. But it counts the - of negative numbers as a match and so does split the chain here too.
So to recap, a perfect answer would be a regex that I can feed to string.split that :
(1). Doesn't match negative numbers even with space(s) between the number and the unary operator.
(2). Doesn't remove the match (separator) in a string.split scenario.

If it is OK for you to have bigger matches, but in which you would only consider the part that is matched in a capture group, then you could require that an operator must be the first one that follows after a digit:
\d[^+*\/-]*([+*\/-])
Here the last character of a match is a binary operator you want to match, and it is put in a capture group.
NB: this does not assume that there cannot be a space between the unary minus and the digits that follow it. So it would also work for "- 9 + 1". And if there are no spaces at all it will not skip the minus in "9-1".
Example in JavaScript:
let s = "(-3 + 8) -7 * - 2"
for (let [_, op] of s.matchAll(/\d[^*\/+-]*([*\/+-])/g))
console.log(op);
// Or as array
let res = Array.from(s.matchAll(/\d[^*\/+-]*([*\/+-])/g), ([_, op]) => op);
console.log(res);
For use with split:
You can use that regular expression with split, but you need to move the characters from the "delimiter-match" back to the preceding "non-delimiter" match. You can do this by chaining a map:
let s = "-5.0 + 9.34 - 6.0 * -2.1 * 3.1 / --2.0";
let res = s.split(/(\d[^*\/+-]*[*\/+-])/g)
.map((m, i, a) => i%2 ? m[m.length-1] : m + (a[i+1] || "").slice(0, -1));
console.log(res)

Use a (positive) lookahead that matches any operator that is immediately followed by a white-space character (\s or just a space )
[+\-*\/](?=\s)
const input = "-5.0 + 9.34 - 6.0 * -2.1 * 3.1 / -2.0";
const rx = /[+\-*\/](?=\s)/g;
console.log(input.match(rx));
Or a negative lookahead that matches any operator that is not immediately followed by a number
[+\-*\/](?!\d)
const input = "-5.0 + 9.34 - 6.0 * -2.1 * 3.1 / -2.0";
const rx = /[+\-*\/](?!\d)/g;
console.log(input.match(rx));
Example for both versions on jsfiddle: https://jsfiddle.net/4bm9Lhug/

You could try following regex.
(?!-\d+)[+*\/-]
Details:
(?!-\d+): we do not get the character minus of negative number
[+*/-]: we get arithmetic operators
Demo

Please try below regex. This considers spaces, brackets and dots as well.
[\d\s)]\s*([+\-*/])\s*[.(\d\-]
Demo
let input = "-5.0 + 9.34 - 6.0 * - 2.1 * 3.1 / - 2.0"
let output = Array.from(input.matchAll(/[\d\s)]\s*([+\-*\/])\s*[.(\d\-]/g), ([i,o]) => o);
console.log(output);

Maybe perl's regex engine handles it differently, or i'm using the wrong perl execution flags, but if I'm interpreting this output correctly, i just wanna quickly point out that :
for malformed inputs like this where it's actually a single negative five ("-5") as the chain of -'s and +'s mostly cancel each other out :
__=' - + - + - 5 '
mawk '$++NF = '"${__}" OFS='\f\r\t' FS='^$' <<< "${__}"
- + - + - 5
-5
+ version info : This is perl 5, version 34, subversion 0 (v5.34.0)
perl -CS -pe 's/([+\-*\/](?=\s))/{{ \1 }}\f/g' <<< "${__}"
{{ - }}
{{ + }}
{{ - }}
{{ + }}
{{ - }}
5
…one of the solutions above would split out 5 numeric operators without associated numbers to their left-hand-side, while also extracting out a positive five ("+5", or simply just "5")

Related

JAVASCRIPT Problem with regex in the .split() method

I have a string formed by number and mathematical operator like "1 + 1 *1" that is the text content of the number appendend on the screen div, I want to form an array of them and then divide it using mathematical operators such as + or - as a divisor, the problem is that when I try to divide them the array is actually divided, except for when the "-" sign is present, in fact if I have as a string "1 + 1 * 1 -1" the result will be an array ["1", "1", "1-1"] while it should be ["1", "1", "1", "1"]
Thanks everyone in advance.
let regex = /[+ | - | * | / ]/
let Arrays
Arrays = screen.textContent.split(regex);
You seem to be confusing alternatives with character sets.
Put the operators inside a character set, and optional spaces around it.
You need to escape - because it's used to separate the ends of a character range (unless you put it at the beginning or end of the character set).
let regex = /\s*[+\-*/]\s*/;
let text = '1 + 1 * 1 -1';
console.log(text.split(regex));
UPDATE
Splitting the string at +, -, *, /
let screentextContent = "1 + 1 * 1 -1"
let regex = /[+\-*/]/
let Arrays
Arrays = screentextContent.split(regex);
console.log(Arrays)
white space after 1 or before 1 will be preserved.
const str = "1 + 1 * 1 - 1";
let regex = /[+|\-|*|/]/
let arr
arr = str.split(regex).map(itm => itm.trim());
console.log(arr);

How can I divide the following equation by regex?

This is my equation
5x^2 + 3x - 5 = 50
I have used this regex
/([+|-])([1-9][a-z])+|([1-9][a-z])+|([+|-])([1-9])+|([1-9])+/mg
but it does not give the results I want.
I want to divide my equation like this
array(
5x^2 ,
3x ,
-5 ,
=50
)
As a starting point, you could split your string by several mathematical operator symbols (for instance +, -, *, / and =). Then you get an array of terms but without the operators that were used to split the string:
const string = "5x^2 + 3x - 5 = 50";
const regex = /\+|\-|\*|\/|=/g;
const result = string.split(regex);
console.info(result);
To retrieve the delimiter characters as well, have a look at this StackOverflow post for example.
First remove the whitespaces.
Then match optional = or - followed by what's not = or - or +
Example snippet:
var str = "5x^2 + 3x - 5 = 50";
let arr = str
.replace(/\s+/g, '')
.match(/[=\-]*[^+=\-]+/g);
console.log(arr);

Regex match a sequence of numbers and a character . between them

So I need to get all ${{1.33.98}} strings from a string.
new RegExp('\\$\\{\\{(.*?)\\}\\}', 'g'); doesnt work well on case like:
${{1.33.98}${{2.44.1}} - should match only ${{2.44.1}} because ${{1.33.98} is missing } at this example.
So it shouldn't match if string missing any of the two {{ or two }} or $.
Between {{ and }} can be only a sequence of numbers separated by a dot - ex. 4.23.4545
Thanks
You match unwelcome values because . can match any char, and thus it matches any chars from the leftmost {{ to the first }} to the right of {{.
You may use
/\${{(\d[\d.]*)}}/g
Or, if the dot-separated number format is important
/\${{(\d+(?:\.\d+)*)}}/g
See this regex demo and this regex demo.
Note that if the strings are prevalidated, and you are sure there are no { and } inside ${{ and }}, you may even use [^{}]* instead of \d[\d.]*:
/\${{([^{}]*)}}/g
So, you either capture
\d[\d.]* - a digit and then 0 or more digits and dots
or
\d+(?:\.\d+)* - 1+ digits and then 0+ repetitions of . and 1+ digits.
JS demo:
const s = '${{1.33.98}${{2.44.1}} ${{1.24.52.44.1}}';
let m = [...s.matchAll(/\${{(\d[\d.]*)}}/g)];
console.log(Array.from(m, x => x[1]));
For legacy ES versions:
var s = '${{1.33.98}${{2.44.1}} ${{1.24.52.44.1}}';
var rx = /\${{(\d[\d.]*)}}/g, results = [], m;
while (m=rx.exec(s)) {
results.push(m[1]);
}
console.log(results);

Regex to find emoji names with colon and skintone

I'm using EmojiMart for my parser.
I've seen this related question but it seem to be different from mine.
So I need to return the emoji names or :code: for them to be able to decode it.
So example I have this text:
:+1::skin-tone-6::man-pouting:Hello world:skin-tone-
6:lalalalla:person_with_pouting_face: :poop::skin-tone-11: mamamia
:smile: :skin-tone-6:
It should match the whole :+1::skin-tone-6:
and not a separate :+1:, :skin-tone-6:: - only if there’s no space between them. (notice the space between :smile: and :skin-tone-6: )
Conditions:
It should only match the :code::skintone: if skintone is 2-6
If I do str.split(regex) this is my expected result (array):
- :+1::skin-tone-6:
- :man-pouting:
- Hello world
- :skin-tone-6:
- lalalalla
- :person_with_pouting_face:
- :poop:
- :skin-tone-11:
- mamamia
- :smile:
- :skin-tone-6:
You may use String#split() with the
/(:[^\s:]+(?:::skin-tone-[2-6])?:)/
regex. See the regex demo.
Details
: - a colon
[^\s:]+ - 1+ chars other than whitespace and :
(?:::skin-tone-[2-6])? - an optional sequence of
::skin-tone- - a literal substring
[2-6] - a digit from 2 to 6
: - a colon.
JS demo:
var s = ":+1::skin-tone-6::man-pouting:Hello world:skin-tone-6:lalalalla:person_with_pouting_face: :poop::skin-tone-11: mamamia :smile: :skin-tone-6:";
var reg = /(:[^\s:]+(?:::skin-tone-[2-6])?:)/;
console.log(s.split(reg).filter(x => x.trim().length !=0 ));
The .filter(x => x.trim().length !=0 ) removes all blank items from the resulting array. For ES5 and older, use .filter(function(x) { return x.trim().length != 0; }).

regexp to strip empty space in an equation

I have an equation where the last operator is specified consecutively it should remove the last operator. I amnot sure how to do this using regex
i.e
var operators = ['*', '-', "+'];
if(operators.indexOf(eql.innerText.slice(-1)) > -1) {
eqText = eqText.replace(/.$/, '');
}
in this case if my equation is 9 * *, i want it to strip the last * along with the space before it.
basically it should be 9 * instead of 9 * *
any pointers
The below regex would remove the last - or * or + along with the preceding space.,
eqText = eqText.replace(/ [-*+]$/, '');
OR
Use the below regex to remove one or more spaces preceeding along with the last special characters.
eqText = eqText.replace(/ +[-*+]$/, '');

Categories