I have a long string where I need to increment every number within it, leaving the rest of the text as it is.
I'm using this function
newHtml = newHtml.replace(/\d+/, function (val) { return parseInt(val) + 1; });
Which works great on numbers that are in free text but fails when the numbers are surrounded by square brackets. Example:
<input id="Form[0]_Phone" name="Form[0].Phone" type="text" value="">
Needs to become
<input id="Form[1]_Phone" name="Form[1].Phone" type="text" value="">
I've used this example to try and help, and I've tried a few variations but my regex skills have failed me.
Any assistance much appreciated.
There is nothing in your pattern causing the described behaviour - numbers in square brackets should also be affected. One obvious issue is you're affecting only the first number found, not all - add the g global flag after the closing forward slash of the pattern.
Works for me - see this Fiddle: http://jsfiddle.net/ypUmg/
You need to use 'global' flag, then it should replace all occurences.
i.e.
newHtml = newHtml.replace(/\d+/g, function (val) { return parseInt(val) + 1; });
See it working here:
http://jsfiddle.net/4S7CE/
Without 'g', it would replace only first instance of the match.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 14 days ago.
This post was edited and submitted for review 14 days ago.
Improve this question
I have an <input type='number'/> element.
I would like to perform a transformation on the number that is input when the submit event triggers. It could be on another event also: I'm open to suggestions, but the transformation should not happen while the user is typing, only when they finish their input.
The transformation should be as follows:
Remove all leading zeros
Remove all ending zeros
Replace all other consecutive zeroes with just one or two zeroes (depending on a variable it should be one or two)
For example: 01002000400 will be converted to 10204
The third rule depends on a boolean variable first_user: if it's true then all inside consecutive zeroes will be converted to one zero, if it's false all inside zeroes will be converted to two zeroes.
Attempt
Here is what I've tried:
ref.value.replace('/^0+/', '')
To also remove the ending zeroes, I tried ^0$, but it didn't work out as I intended: there was no effect.
And I have no idea how to implement the third rule.
How can I achieve this?
You can do this with a single replace call. The three cases can be checked in this order:
Zeroes at start of string
Zeroes at end of string
Zeroes (more than one) anywhere else: capture the first zero in capture group
As replacement, output the string captured by the capture group. As this group only captures a zero when the third case kicks in, this practically means that all other zeroes are removed.
I believe an exception to this rule has to be introduced for when the number is exactly 0. I guess you want to keep that single zero then. To make that happen, I would restrict the first two rules as follows:
Zeroes at start of string when followed by a non-zero
Zeroes at end of string when following a non-zero
Zeroes (more than one) anywhere else: capture the first zero in capture group
The third case will now also apply when the input consists of only zeroes.
You could use the submit event, but maybe it is interesting too to use the change event: it does not trigger while the user is typing, but does trigger when the user "commits" the value, i.e. when focus is moved to another element, or another tab/window is selected, or the up/down controls are used on the input widget, or the form is submitted, ...
const inputDouble = document.getElementById("double")
const input = document.getElementById("inp");
document.addEventListener("change", function () {
const regex = inputDouble.checked
? /^0+(?=[^0])|(?<=[^0])0+$|(00)0+/g
: /^0+(?=[^0])|(?<=[^0])0+$|(0)0+/g
input.value = input.value.replace(regex, "$1");
});
<input id="double" type="checkbox"> Double zeroes<br>
Number to clean: <input id="inp" type="number"><br>
<button>Fake submit</button>
A good solution would be to implement a simple algorithm that does what you need. Example:
Remove from the first position (0) on until you find a non-zero number;
Remove from the last position backwards (string.length-1) until you find a non-zero number;
Walk the string after the modification above and: if the current number is a non-zero create a new string with it, if it is zero and the previous was not, include it on the new string, if the previous was zero, ignore it.
That should make a very simple method and will work better then a regex.
For the onSubmit trigger, I think it will work fine. I would use onChange and store it in a hidden field just, but I thing onSubmit will do the trick
I think you're overthinking it. To replace multiples of anything with a single version of that thing you just need to target one or more things and in your replace function, replace with a single thing
You don't really need to specify the beginning or the end. You just need to specify any one or more 0 and then replace with a single 0
Try this:
const singleZeros = '10020004'.replace(/(0+)/g, '0')
console.log(singleZeros);
For removing the leading and trailing 0's, there might be a better way but off the top of my head, this is what I'd do:
const removeStart = (s) => s.startsWith('0') ? s.slice(1) : s;
const removeEnd = (s) => s.endsWith('0') ? s.slice(0, s.length - 1) : s;
const zerosOnEnds = '0102040'
const zerosTrimmed = removeEnd(removeStart(zerosOnEnds));
console.log(zerosTrimmed)
Maybe a simple solution would be to create a conversion function to run on submit. Something like:
answer = 10020004
function transform(answer){
final_answ = ''
index = 0
zero_index = -2
while(index<answer.toString().length){
if (answer.toString()[index] !== '0'){
final_answ += answer.toString()[index]
} else if (index === zero_index+1){
zero_index = index
} else {
final_answ += answer.toString()[index]
zero_index = index
}
index++
}
}
Transforming the user response to string will also make it easy for you to remove starting and ending '0'.
If this does not help will you please, provide more information?
Hope it helps.
You can try this
let str = '001002000400'
str = str.replace(/^0*(\d+?)0*$/, (matchs, p1) => {
return p1.replaceAll(/([^0]+)0+/g,'$10')
})
console.log(str); //10204
from your post all you need is just a regex to replace first zero with empty string and other zero in middle if they're more than 1 replace them and just keep one
what you will be need first thing in your code you're used the regex as string'/^0+/' and that's not the true way to use regex you should remove the string quotes and write your regex inside forward slash / like /regex/
second: you need to use regex modifiers in your case you need g modifier
for more info about regex you can check some tutorials like that or quick reference like w3schools reference
here's your regex
//Result: 104057
console.log("0100400057".replace(/^0|(0)+(?=0)/g, ""))
I hope I can explain myself clearly here and that this is not too much of a specific issue.
I am working on some javascript that needs to take a string, find instances of chars between square brackets, store any returned results and then remove them from the original string.
My code so far is as follows:
parseLine : function(raw)
{
var arr = [];
var regex = /\[(.*?)]/g;
var arr;
while((arr = regex.exec(raw)) !== null)
{
console.log(" ", arr);
arr.push(arr[1]);
raw = raw.replace(/\[(.*?)]/, "");
console.log(" ", raw);
}
return {results:arr, text:raw};
}
This seems to work in most cases. If I pass in the string [id1]It [someChar]found [a#]an [id2]excellent [aa]match then it returns all the chars from within the square brackets and the original string with the bracketed groups removed.
The problem arises when I use the string [id1]It [someChar]found [a#]a [aa]match.
It seems to fail when only a single letter (and space?) follows a bracketed group and starts missing groups as you can see in the log if you try it out. It also freaks out if i use groups back to back like [a][b] which I will need to do.
I'm guessing this is my RegEx - begged and borrowed from various posts here as I know nothing about it really - but I've had no luck fixing it and could use some help if anyone has any to offer. A fix would be great but more than that an explanation of what is actually going on behind the scenes would be awesome.
Thanks in advance all.
You could use the replace method with a function to simplify the code and run the regexp only once:
function parseLine(raw) {
var results = [];
var parsed = raw.replace(/\[(.*?)\]/g, function(match,capture) {
results.push(capture);
return '';
});
return { results : results, text : parsed };
}
The problem is due to the lastIndex property of the regex /\[(.*?)]/g; not resetting, since the regex is declared as global. When the regex has global flag g on, lastIndex property of RegExp is used to mark the position to start the next attempt to search for a match, and it is expected that the same string is fed to the RegExp.exec() function (explicitly, or implicitly via RegExp.test() for example) until no more match can be found. Either that, or you reset the lastIndex to 0 before feeding in a new input.
Since your code is reassigning the variable raw on every loop, you are using the wrong lastIndex to attempt the next match.
The problem will be solved when you remove g flag from your regex. Or you could use the solution proposed by Tibos where you supply a function to String.replace() function to do replacement and extract the capturing group at the same time.
You need to escape the last bracket: \[(.*?)\].
I'm not very good with RegEx, and am trying to learn. I have inherited a project which contains the following line of code:
function findCourseIdFromForm(where) {
var matchRegex = /\[course-[0-9]*\]/;
var replaceRegex = /\[|\]|[a-z]|\-/g;
return $(".cnumber", where.parent()).attr("name").match( matchRegex )[0].replace( replaceRegex,"" );
}
I'm not entirely sure what this piece of code is trying to do, but I know that it is causing issues on my page. I'm using jQuery validator and this specific component (".cnumber") is causing the validation to fail and I'm not entirely sure why, so some insight into this line is appreciated.
The .cnumber field in the HTML looks like this:
<input type="hidden" name="courses[course-0][cnumber]" class="cnumber" />
This function takes where node, gets its parent, finds .cnumber node within the parent, then takes [course-0] part and finally remove all [, ], -, and lowercase letters.
So the function returns the number that stands after [course- part, or empty string if there is no number
It strips out [, ], lowercase letters and - from the name attribute in the tag, presumably to return the course number.
It just get the course number. In you example, it return 0
I am trying to build a sort of intelli-sense text input box, where as the user types, the 'and' is replaced by 'AND \n' (i.e. on each 'and', the 'and' is capitalized and user goes to new line).
The Javascript I used for this is:
function Validate()
{
document.getElementById("search").value = document.getElementById("search").value.replace("and","AND \n"); //new line for AND
}
The HTML part is like this:
< textarea type="text" name="q" id="search" spellcheck="false" onkeyup='Validate();'>< /textarea>
Though the above script works well on Firefox and Chrome, it sort-of misbehaves on Internet Explorer (brings the cursor to the end of the text on each 'KeyUp').
Also the above code doesn't work for the other variants of 'and' like 'And', 'anD' or even 'AND' itself.
I think the actual answer here is a mix of the two previous:
onkeyup="this.value = this.value.replace(/\band\b/ig, ' AND\n')"
You need the i to make the search case insensitive and the g to make sure you replace all occurrences. This is not very efficient, as it'll replace previous matches with itself, but it'll work.
To make it a separate function:
function validate() {
document.getElementById('search') = document.getElementById('search').replace(/\band\b/ig, ' AND\n');
}
If you alter the textarea contents while the user is typing the caret will always move to the end, even in Firefox and Chrome. Just try to edit something you already wrote and you'll understand me. You have to move the caret to the exact position where the users expects it, which also implies you have to detect text selections (it's a standard behaviour that typing when you have a selection removes the selected text).
You can find here some sample code. You might be able to use the doGetCaretPosition(), setCaretPosition() functions.
I tried to work around the problem and solved by using the following javascript:
function Validate() {
if( document.getElementById("search").value.search(/\band$(?!\n)/i) >= 0 ){ // for maintaining cursor position
document.getElementById("search").value = document.getElementById("search").value.replace(/\band$(?!\n)/i,"AND\n"); //new line for AND
}
}
Thin slicing the above problem and solution:
1) The function was being called on each key up, thus earlier "AND\n" was being repeated on each key up, thus inserting a blank line on each key press. I avoided the above by using the regex:
/\band$(?!\n)/i
\b = Like Word (to avoid SAND)
$ = End of line (as "and" will be replaced by "AND\n" thus it will always be end of line)
(?!\n) = Not followed by new line (to prevent repeatedly replacing "AND\n" on each key press)
i = To cover all variants of "and" including "And","anD" etc.
2) Internet Explorer was misbehaving and the cursor position was not maintained (moved to end) when the input was re-edited. This was caused (as hinted by Alvaro above) due to the replace function.
Thus I inserted an "if" statement to call replace function only when it is needed, i.e. only when there is some "and" needing replacement.
Thanks everyone for the help.
try using the following replace() statement:
replace(/\band(?!$)/ig, "And\n")
since this is being called repeatedly against the altered string you have to make sure that the "and" is not followed by a line break.
example (uses a loop and function to simulate the user typing the letters in):
function onkeyup() {
var str = this;
return this.replace(/\band(?!$)/ig, "And\n");
};
var expected = "this is some sample text And\n is separated by more text And\n stuff";
var text = "this is some sample text and is separated by more text and stuff";
var input = "";
var output = "";
for(var i = 0, len = text.length; i < len; i++ ) {
input += text.substr(i,1);
output = onkeyup.call(input);
}
var result = expected == output;
alert(result);
if( !result ) {
alert("expected: " + expected);
alert("actual: " + output);
}
you can test this out here: http://bit.ly/8kWLtr
You need to write a JS code that run in both IE and FireFox. I think this is what you need:
var s = document.getElementbyId('Search');
s.value = s.value.replace('and', 'AND \n');
I think you want your replace call to look like this:
replace(/\band\b/i,"AND \n") (see below)
That way it is not case sensitive (/i), and only takes single words that match and, so 'sand' and similar words that contain 'and' don't match, only 'and' on it's own.
EDIT: I played around with it based on the comments and I think this working example is what is wanted.
Replace the onKeyUp event with onBlur:
<textarea type="text" name="q" id="search" spellcheck="false" onblur='Validate();'></textarea></body>
So that the validate function is only run when the user leaves the text box. You could also run it onSubmit.
I also added a global switch (g) and optional trailing whitespace (\s?) to the regex:
replace(/\band\b\s?/ig,"AND \n")
This causes input like this:
sand and clay and water
to be transformed into this when you leave the text box:
sand AND
clay AND
water
You should probably test this against a bunch more cases.
Friends,
I'm new to both Javascript and Regular Expressions and hope you can help!
Within a Javascript function I need to check to see if a comma(,) appears 1 or more times. If it does then there should be one or more numbers either side of it.
e.g.
1,000.00 is ok
1,000,00 is ok
,000.00 is not ok
1,,000.00 is not ok
If these conditions are met I want the comma to be removed so 1,000.00 becomes 1000.00
What I have tried so is:
var x = '1,000.00';
var regex = new RegExp("[0-9]+,[0-9]+", "g");
var y = x.replace(regex,"");
alert(y);
When run the alert shows ".00" Which is not what I was expecting or want!
Thanks in advance for any help provided.
strong text
Edit
strong text
Thanks all for the input so far and the 3 answers given. Unfortunately I don't think I explained my question well enough.
What I am trying to achieve is:
If there is a comma in the text and there are one or more numbers either side of it then remove the comma but leave the rest of the string as is.
If there is a comma in the text and there is not at least one number either side of it then do nothing.
So using my examples from above:
1,000.00 becomes 1000.00
1,000,00 becomes 100000
,000.00 is left as ,000.00
1,,000.00 is left as 1,,000.00
Apologies for the confusion!
Your regex isn't going to be very flexible with higher orders than 1000 and it has a problem with inputs which don't have the comma. More problematically you're also matching and replacing the part of the data you're interested in!
Better to have a regex which matches the forms which are a problem and remove them.
The following matches (in order) commas at the beginning of the input, at the end of the input, preceded by a number of non digits, or followed by a number of non digits.
var y = x.replace(/^,|,$|[^0-9]+,|,[^0-9]+/g,'');
As an aside, all of this is much easier if you happen to be able to do lookbehind but almost every JS implementation doesn't.
Edit based on question update:
Ok, I won't attempt to understand why your rules are as they are, but the regex gets simpler to solve it:
var y = x.replace(/(\d),(\d)/g, '$1$2');
I would use something like the following:
^[0-9]{1,3}(,[0-9]{3})*(\.[0-9]+)$
[0-9]{1,3}: 1 to 3 digits
(,[0-9]{3})*: [Optional] More digit triplets seperated by a comma
(\.[0-9]+): [Optional] Dot + more digits
If this regex matches, you know that your number is valid. Just replace all commas with the empty string afterwards.
It seems to me you have three error conditions
",1000"
"1000,"
"1,,000"
If any one of these is true then you should reject the field, If they are all false then you can strip the commas in the normal way and move on. This can be a simple alternation:
^,|,,|,$
I would just remove anything except digits and the decimal separator ([^0-9.]) and send the output through parseFloat():
var y = parseFloat(x.replace(/[^0-9.]+/g, ""));
// invalid cases:
// - standalone comma at the beginning of the string
// - comma next to another comma
// - standalone comma at the end of the string
var i,
inputs = ['1,000.00', '1,000,00', ',000.00', '1,,000.00'],
invalid_cases = /(^,)|(,,)|(,$)/;
for (i = 0; i < inputs.length; i++) {
if (inputs[i].match(invalid_cases) === null) {
// wipe out everything but decimal and dot
inputs[i] = inputs[i].replace(/[^\d.]+/g, '');
}
}
console.log(inputs); // ["1000.00", "100000", ",000.00", "1,,000.00"]