regexp to strip empty space in an equation - javascript

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(/ +[-*+]$/, '');

Related

Regex to select text without white spaces with restrictions

I need to select some text between % signs where there is not white space between 2 %.
This should match:
%link%
This shouldn't:
%my link%
This easy regex would do the trick:
/%\S*%/g
But there is a catch: I can add a prefix: % and a suffix: % but the regex must contain this between these: (.+?)
(it's a third party script).
So this is the regex I need to adjust:
/%(.+?)%/
Because of "(.+?)" I need a workaround, any idea?
UPDATE:
All of these are true for a perfect regex:
regex = /%(.+?)%/g // default regex which allows spaces so it's not good
regex.test('%link%')
regex.test('%my link%') === false
regex.toString().includes('(.+?)')
You can use
var some_hardcoded_value = ".+?";
var regex = new RegExp("%(?=[^\\s%]+%)" + some_hardcoded_value + "%", "g");
See the regex demo.
Details:
% - a % char
(?=[^\s%]+%) - a positive lookahead that requires any one or more chars other than whitespace and % immediately to the right of the current location
(.+?) - Group 1: any one or more chars other than line break chars
% - a% char.
See a JavaScript demo:
const some_hardcoded_value = ".+?";
const regex = new RegExp("%(?=[^\\s%]+%)(" + some_hardcoded_value + ")%", "g");
const str = "%link% This shouldn't %my link% %%link,,,,,%%%%";
console.log(Array.from(str.matchAll(regex), x => x[1]));

Match arithmetic operators in a string but not negative numbers

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")

How to get first 2 words?

Let data.title be ABC XYZ PQRS - www.aaa.tld.
Output needs to be like this ABC+XYZ
i've tried this:
var t = data.title.split(' ').join('+');
t = t.replace(/(([^\s]+\s\s*){1})(.*)/,"Unknown");
$("#log").text(t);
Here is one way to do it, no regex though, it only grabs the first two words and must have a space between those words.
First we split into and array, then we slice that array from the 0 index to 2(exclusive) or 1, and finally we join them with a '+':
var x = 'ABC XYZ PQRS';
var y = x.split(' ').slice(0,2).join('+');
// y = "ABC+XYZ"
Working Fiddle
Try using .match() with RegExp /([\w+]+)/g; concatenate first match, + character, second match
var matches = "ABC XYZ PQRS - www.aaa.tld".match(/([\w+]+)/g);
console.log(matches[0] + "+" + matches[1])
This is my general function for first n words. Haven't tested it extensively but it is fast even on long strings because it doesn't use a global regex or split every word. You can fine tune the regex for dealing with punctuation. I'm considering a hyphen as a delimiter but you can move that to the word portion instead if you prefer.
function regFirstWords(s, n) {
// ?: non-capturing subsequent sp+word.Change {} if you want to require n instead of allowing fewer
var a = s.match(new RegExp('[\\w\\.]+' + '(?:[\\s-]*[\\w\\.]+){0,' + (n - 1) + '}'));
return (a === undefined || a === null) ? '' : a[0];
}
To satisfy the OP's request to replace with '+'
regFirstWords('ABC XYZ PQRS - www.aaa.tld',2).replace(/\s/g,'+')

Javascript-only wordwrap function on whitespace?

Most wordwrap functions I've found are bound to css and/or a browser dom.
I'm working in a javascript environment (rhino) and need to find or design a better word wrap that breaks on whitespace before a given line length value.
My current solution just searches for the last white space before the given character, then clips the left side, storing it as a line of output (in an array return). Repeat until no more text remains.
Hoping someone has seen something elegant.
You could write something like:
let wordwrapped = (original + ' ').replace(/(\S(.{0,78}\S)?)\s+/g, '$1\n').trim();
That will replace \s+ with \n after at-least-one,-at-most-eighty,-preferably-as-many-as-possible characters. (Note: if there are more than eighty characters in a row without whitespace, then there will be a line-break before and after them, but no wrapping will take place inside them.)
See it in action:
// generate random sequence of 500 letters and spaces:
let original = String.fromCharCode.apply(String, Array.from({length: 500}, () => 64 + Math.floor(Math.random() * 27))).replace(/#/g, ' ');
// perform word-wrapping:
let wordwrapped = (original + ' ').replace(/(\S(.{0,78}\S)?)\s+/g, '$1\n').trim();
// show the results in the <pre> elements:
document.getElementById('ruakh-original').innerText = 'original:\n' + original;
document.getElementById('ruakh-word-wrapped').innerText = 'word-wrapped:\n' + wordwrapped;
<pre id="ruakh-original"></pre>
<pre id="ruakh-word-wrapped"></pre>
This regex will wrap every 0-width character and respect whitespaces and hyphens also cuts words longer than width characters. Try it out on regexr.
/**
* Wrap every 0-`width` character and respect whitespaces and hyphens also cuts words longer than `width` characters.
* #param str The string to wrapped
* #param width The maximum length a string can be
*/
function wordwrap(str, width) {
return str.replace(new RegExp(`(?:\\S(?:.{0,${width}}\\S)?(?:\\s+|-|$)|(?:\\S{${width}}))`, 'g'), s => `${s}\n`).slice(0, -1);
}
function wordwrap(str, width) {
return str.replace(new RegExp('(?:\\S(?:.{0,' + width + '}\\S)?(?:\\s+|-|$)|(?:\\S{' + width + '}))', 'g'), function (s) {return s + '\n'}).slice(0, -1);
}
console.log(wordwrap('This is my regular-expression. It will wrap every 0-20 character and respect whitespaces and hyphens, also cuts reallylongwordslikethis.', 20));
RegEx is really the way to go. /.{0,79}(?:\s|$)/g will grab the longest line under 80 characters ending with a character or the end of the file. Calling exec multiple times will extract each line.
var text = "";
var regex = /.{0,79}(?:\s|$)/g;
var lines = [];
var line;
while (line = regex.exec(text)) {
lines.push(line);
}

Currency / Percent Regular Expression

I have to match values like
€ 6.483,00
OR values like
18,50%
OR, again,
+65,86 %
in a Javascript function, which I drafted as:
function(s) {
return /^[0-9]?[0-9,\.]*$/.test(s);
}
but, obviously, it's not working... how should it be changed?
^(?:€|\+)?\s*\d+(?:\.?\d{3})*(?:,\d+)?\s*%?\s*$
See it here on Regexr
Start of the string, an optional € or +, then optional whitespace, Then there should be at list one digit, followed by an optional dot and three digits, then an optional fraction, optional whitespace, optional % more optional whitespace and then the end of the string,
var sample = [
"€ 6.483,00",
"18,50%",
"+65,86 %"
]
for(var i = 0; i < sample.length; i++) {
var input = sample[i];
var regex = /^(\u20ac ?)?\+?\d+(\.\d+)?(\,\d+)?( ?%)?$/
console.log(input + "\t" + regex.test(input));
}
If there are cases that do not/should not match then let me know.

Categories