Split Regex anything but number - regex

I'm trying to do a monthly installment with some possibilities, like:
3x // result == 3
10x // result == 10
30 // result == 1
30./60 // result == 2
30#60#90 // result == 3
30 60 90 120 // result == 4
30-60- 90-120--150 // result == 5
30x60x90x120x150x180 // result == 6
and so on... I'm trying to get any character, with multiple spaces OR multiple characters (equals to each other or not). I reach the following code so far... but I could add the exception for numbers, and the result are not always right.
var pattern = /(\#?[a-zA-Z(!0-9) \/]+)/g;
var a = '30/60/90';
var b = a.split(pattern);
$('#yyy').text(b);
$('#xxx').text(b.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label id="yyy"></label>
<br><br>
<label id="xxx"></label>
I'm HORRIBLE in regex, really "noob" to it, so if could explain in the answer/comment WHY you are doing specific regex, I would be please (so I can learn instead of copy/paste without too much clue)

I'm not so sure I understood your question correctly, but I'll answer as I understood it:
To split on anything except numbers, the solution would be:
var pattern = /\D+/g;
var a = '30/60/90';
var b = a.split(pattern);
$('#yyy').text(JSON.stringify(b));
$('#xxx').text(b.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label id="yyy"></label>
<br><br>
<label id="xxx"></label>
The regex is pretty simple: \d means a digit, so \D means not a digit, so \D+ means a series of characters that are not digits.
It may be even easier if you try matching instead of splitting:
var pattern = /\d+/g;
var a = '30/60/90';
var b = [];
var m;
while (m = pattern.exec(a))
b.push(m[0]);
$('#yyy').text(JSON.stringify(b));
$('#xxx').text(b.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label id="yyy"></label>
<br><br>
<label id="xxx"></label>
In that case \d+ means a series of digits.
For reference, in JS:
\d is shorthand for [0-9]
\D is shorthand for [^0-9]

Related

How to assert that a text ends with digits in protractor

I would like to assert in Protractor that a link text is composed by the following way: text-1 (where text is a variable, and the number can be composed by any digits).
I tried the following:
browser.wait(
ExpectedConditions.visibilityOf(
element(by.xpath(`//a[#class = 'collapsed' and starts-with(text(), '${text}') and ends-with(text(), '-(/d+)')]`))),
5000)
and
browser.wait(
ExpectedConditions.visibilityOf(
element(by.xpath(`//a[#class = 'collapsed' and starts-with(text(), '${text}') and ends-with(text(), '/^-(/d+)$/')]`))),
5000)
Unfortunately, none of the above xpaths worked.
How can I fix this?
If you change the way to declare the variable and your second predicate you can go with :
//a[#class='collapsed'][starts-with(text(),'" + text_variable + "')][number(replace(.,'^.*-(\d+)$','$1'))*0=0]
where [number(replace(.,'^.*-(\d+)$','$1'))*0=0] test for the presence of a number at the end of a string.
Example. If you have :
<p>
<a class="collapsed">foofighters-200</a>
<a class="collapsed">foofighters</a>
<a class="collapsed">boofighters-200</a>
<a class="collapsed">boofighters-200abc</a>
</p>
The following XPath :
//a[#class='collapsed'][starts-with(text(),'foo')][number(replace(.,'^.*-(\d+)$','$1'))*0=0]
will output 1 element :
<a class="collapsed">foofighters-200</a>
So in Protractor you could have :
var text = "foo";
browser.wait(ExpectedConditions.visibilityOf(element(by.xpath("//a[#class='collapsed'][starts-with(text(),'" + text + "')][number(replace(.,'^.*-(\d+)$','$1'))*0=0]"))), 5000);
...
You can use regexp for this:
await browser.wait(async () => {
return new RegExp('^.*(\d+)').test(await $('a.collapsed').getText());
}, 20000, 'Expected link text to contain number at the end');
Tune this regex here if needed:
https://regex101.com/r/9d9yaJ/1

Regex input formatting with vue.js

I'm trying to format user input in vue.js. The input is representing time mm.ss. Two numbers then dot and two numbers again. The dot should appear automatically after first two number are typed. I was able to achieve it using rexeg here's the codepen:
https://codepen.io/Marek92/pen/KKKqKjx
<div id="app">
<h1>{{ title }}</h1>
<input type="text" v-model="performance">
</div>
new Vue({
el: '#app',
data: {
title: 'Input formating!',
performance: '12.00'
},
watch: {
performance() {
this.performance = this.performance.replace(/[^0-9]/g, '')
.replace(/^(\d{2})(\d{2})?/g, '$1.$2')
.substr(0, 5);
}
}
});
However the problem is when the input is there. Let's say '12.00' and you start deleting the number using backspace from the end. You get stuck on the dot. Unable to delete the dot and that is my problem. How can I change the regex to be able delete the dot? Or some other solution?
Please look at below code-
new Vue({
el: '#app',
data: {
title: 'Input formating!',
performance: '12.00'
},
watch: {
performance() {
var a = this.performance.replace(/[^0-9]/g, '')
.substr(0, 5);
if (a.length >= 3) {
a = a.substring(0, 2) + '.' + a.substring(2, a.length)
}
this.performance =a;
}
}
});
Explanation: Try to add a point after 2 digit when there is more than 2 digits. otherwise remove all characters except digits.
https://codepen.io/ashfaq_haq/pen/xxxrbYO
I had ESLint build rules in place that were not allow me to use Regex. If you have the same issue simply removed the rules by configuring the eslintrc.js file
'rules': {
// allow regex test of phone numbers
'no-useless-escape': 0
}
and then you can create the const and use the test method. worked great for my phone number check.
const phoneNumberFormat =
new RegExp(/^[+]?(\d{1,2})?[\s.-]?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/)
const validatePhoneNumber = (context, event) => {
let address = context.address
if (!phoneNumberFormat.test(address.phoneNumber)) {
return false
}
return true
}
Your second capture group is optional, so it will try to add the . when you delete it because a two digit number also matches the regex. One option is to remove the optional syntax ?, use /^(\d{2})(\d{2})/g or /^(\d{2})(\d{1,2})/g so that it only starts to format when there are more than two numbers.
See https://codepen.io/leopsidom/pen/zYYzxKY.

delete all text after the nth occurance of a whitespace

I used this snippet to make line breaks inside text. how can I delete the text behind the nth whitespace completely?
var str:String = ("This is just a test string").replace(/(( [^ ]+){2}) /, "$1\n");
regards
This works using regex (([^ ]* ){2}).* and replace pattern $1:
function removeAfterNthSpace() {
var nth = parseInt($("#num").val());
var regEx = new RegExp("(([^ ]* ){" + nth + "}).*", "g")
var str = ("This is just a test string").replace(regEx, "$1");
console.log(str);
}
$('#num').change(removeAfterNthSpace);
removeAfterNthSpace();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" id="num" value="2" />
See it working on regex101.

Angular regex error

I'm creating a form in Angular that requires the rate field to take only numbers with 2 decimal places. My HTML is as follows:
<input type="number" class="form-control" (keypress)="_keyPress($event)" (ngModelChange)="Valuechange($event,salesorder,'Rate')" [ngModelOptions]="{standalone: true}" name="customerCode" #customerCode="ngModel" [(ngModel)]="salesorder._dto.rate" [style]="{'text-align':'right'}" />
On every keypress event I'm calling _keyPress() method as follows:
_keyPress(event: any) {
const pattern = /[0-9\+\.\ ]/;
let inputChar = String.fromCharCode(event.charCode);
if (!pattern.test(inputChar)) {
// invalid character, prevent input
event.preventDefault();
}
}
The above regex works fine but does not restrict the number to 2 decimal places. I tried with various regex but could not implement the restriction to 2 decimal places. The last regex I used to do the same is as follows:
const pattern = /[0-9]+(.[0-9]{0,2})/;
I have no much idea about regex.
You can try following regex:
const pattern = /^[0-9]*\.[0-9]{2}$/
Or you may use shorthand character class \d instead of [0-9] i.e:
const pattern = /^\d*\.\d{2}$/
Description:
[0-9]{2}$ or \d{2}$ will make sure that there are exactly 2 numbers after decimal point.
You may replace * with + if there must be at least one number before point.
To restrict the decimal place to 2 digits, you could use {2}.
{0,2} means match zero, one or two times.
[0-9]+(\.[0-9]{2})
Note
This uses an unnecessary capturing group (\.[0-9]{2}) which could be written as \.[0-9]{2}
You could also use anchors to match from the beginning ^ to the end $:
^[0-9]+(\.[0-9]{2})$
or
^[0-9]+\.[0-9]{2}$
var pattern = /^[0-9]+(\.[0-9]{2})$/;
var inputs = [
"22.65",
"22.6",
"22.656"
];
for (var i = 0; i< inputs.length; i++) {
console.log(pattern.test(inputs[i]))
}

Regex to validate date yyyy-mm-dd while typing (on keyup)

I need to validade date yyyy-mm-dd on user keyup.
I'm currently at validating yyyy-mm with this Regex
^\d{0,4}$|^\d{4}[-]$|^\d{4}[-](0?[0-9]|1[012])$
JS Fiddle
But I need validade others part of date. Can anyone help me?
Explanation: Vague checking input while typing if it matches the desired format yyyy-mm-dd.
Modified your current regex a bit and added the dd part so it becomes
^\d{0,4}$|^\d{4}-0?$|^\d{4}-(?:0?[1-9]|1[012])(?:-(?:0?[1-9]?|[12]\d|3[01])?)?$
(?: opens a non capture group for alternation
0?[1-9]? optional 1-9 with preceding 0 or zero
[12]\d days 10-29
3[01] days 30 and 31
See the demo at regex101
For dd-mm-yyyy try this variant:
^0?$|^(?:0?[1-9]|[12]\d|3[01])(?:-(?:(?:0$|0?[1-9]|1[012]?)(?:-\d{0,4})?)?)?$
Or for mm-dd-yyyy that one:
^0?$|^(?:0?[1-9]|1[012]?)(?:-(?:(?:0$|0?[1-9]|[12]\d|3[01])(?:-\d{0,4})?)?)?$
This does not actually validate a date (leap years/28-31 days). Just loose checks input while typing, you can probably make it shorter. As follows an example with the yyyy-mm-dd pattern.
$("#date").on("keyup", function()
{
let valid = /^\d{0,4}$|^\d{4}-0?$|^\d{4}-(?:0?[1-9]|1[012])(?:-(?:0?[1-9]?|[12]\d|3[01])?)?$/.test(this.value), input = this.value;
if(!valid) {
this.value = input.substring(0, input.length - 1);
this.style.backgroundColor = '#EEA39C';
}
setTimeout(() => { this.style.backgroundColor = '#88DD85'; }, 700);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="date" style="font-size: 20px" maxlength="10" type="text" />
To validate the full date when typed/submitted see this answer of #PhiLho and rearrange it to the desired format, e.g. for yyyy-mm-dd
function isValidDate(date)
{
var matches = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(date);
if (matches == null) return false;
var y = matches[1];
var m = matches[2] - 1;
var d = matches[3];
var composedDate = new Date(y, m, d);
return composedDate.getDate() == d &&
composedDate.getMonth() == m &&
composedDate.getFullYear() == y;
}
<input type="text" id="date" style="font-size: 17px" value="2016-03-16">
<button onclick="alert(
isValidDate(getElementById('date').value)
);" style="font-size: 17px">check date</button>
This regex is a bit complex, but check the whole Gregorian rule.
regExp = "(((\d{2}(([13579][26])|([2468][480])|(0[48])))|(([13579][26])|([02468][480]))00)-02-29)|(\d{4}-((?:(0[13578]|1[02])-([0-2]\d|3[0-1]))|(?:(0[469]|11)-([0-2]\d|30))|(?:02-([0-1]\d|2[0-8]))))"
var regExp = /^(\d{4})-(\d{2})-(\d{2})$/
regExp.test(value);