Find and alter text in a string based on ln # and character # - javascript

How can I prepend characters to a word located at a particular Ln # and character # in text?
Example:
The use case is when a person enters code into a textarea (like jsFiddle), I find and replace some of their variables. I know the line # and character location of the start and end of these variables.
Example Text:
var usersCode = $('textarea').val();
console logging usersCode:
print "My first name is: " + first_name
print "This is awesome."
print "My last name is: " + last_name
How could I find the word starting at Ln 0, Char 29 and ending at Ln 0, Char 39 (first_name) and turn it into MyObj.first_name.value?
print "My first name is: " + MyObj.first_name.value
print "This is awesome."
print "My last name is: " + last_name
Maybe I can use a regex that translates "line number" into counting the number of \n occurrences? And then moving the pointer in by the number of characters?
I have to use Ln # and Char # for many details that I won't go into here. I am aware of many simpler alternatives if I wasn't constrained to using Ln # and Ch #.

You can save the lines of the textarea into an array:
var lines = $('#textarea').val().split(/\n/);
And from there you take the substring of a particular line and assign it to your object:
MyObj.first_name.value = lines[0].substring(29,39)
Hope that helps!

If you're just trying to replace first_name and last_name the simplest solution would be to use replace(), for example:
usersCode.replace("first_name", MyObj.first_name.value);
usersCode.replace("last_name", MyObj.last_name.value);
If you're insistent on doing the line number and character number specific thing, we can arrange that, but it's not at all necessary for what it seems like you're asking for. Perhaps I'm mistaken, though.
Update:
Okay so you want to replace all instances? Finding line numbers and all that is still unnecessary, just use this:
usersCode.replace(/first_name/g, MyObj.first_name.value);
usersCode.replace(/last_name/g, MyObj.last_name.value);
g is a RegEx flag for global searching.
Update 2:
usersCode.split("\n")[lineNumber - 1].replace(usersCode.split("\n")[lineNumber - 1].substr(29, 39), MyObj.first_name.value);
You can replace 29 and 39 with variables startChar and endChar respectively. lineNumber will also need to be provided by you.

RegEx can easily search based on characters but not via position. Though you can still do it using regEx but the soultion will become more and more complex. For this case you don;t need a pure RegEx answer. Code below is what you need.
k=$('#regex_string').val()
function findAndReplaceWord(lineNo, startPos, endPos, replaceWith) {
var line = k.split(/\n/)[lineNo];
if(line) {
var word = line.substring(startPos, endPos)
return k.replace(word, replaceWith)
}
}
findAndReplaceWord(0, 29, 39, MyObj.first_name.value)

Related

Javascript - Regex for double quotes on inch measurements

Given measurement data like:
2"
3" Contract
When coming back from the server it looks like this:
"\"2\"\"\""
"\"3\"\" Contract\""
e.g. as shown within the image:
I want the data to be displayed as a proper measurement to the user. So:
2"
3" Contract
As shown above
I resorted to complicated regexes to get the second example working (3" Contract) but it would just turn 2" to 2.
let measurement_formatted = value.replace("\"\"", '\"');
measurement_formatted = measurement_formatted.replace(/(^"|"$)/g, '');
measurement_formatted = measurement_formatted.replace("\"", '\"');
How can I develop a proper regex for both cases?
First of all, those \ before the " are just put there to tell you that the " (preceded by a\) is being escaped.
Based on that, the string "\"3\"\" Contract\"" is the same as '"3"" Contract"' because escaping " is no longer needed when the string is delimited by ' character.
To answer, or rather land some help (which I'll always gladly do), you may use the following regex /^"*|(\D)"/g in conjunction with the replace method :
/ : tells the JS engine that we're creating a regex.
^"* : tells the JS engine to match any " at the start of the string (0 or more).
| : acts as the logical OR operator.
(\D)" :
(\D) : creates a matching group of any NON-NUMERIC character.
" : the literal " character.
g : tells the JS engine to match all the occurrences of that regex.
The idea here is to tell the replace method to replace all " characters that are preceded by a non-numeric character with that matched non-numeric character and entirely delete the " character.
Here's a live example :
const regex = /^"*|(\D)"/g;
/** $1 : means write down the first matched capturing group */
console.log('"3"" Contract"'.replace(regex, '$1')); // 3" Contract
console.log('2"'.replace(/^"*|(\D)"/g, '$1')); // 2"
Learn more about the replace method.
Hope i managed to land some help.

Replacing character after certain character length

I trying to do a function to replace all the character after a certain length of character to asterisk, and so far what i did is like this.
var text = 'ABCDEFG';
var newText = text.substring(0,3) + text.substring(3).replace(/\S/g,'*');
If would give me what I need, but it is fairly inefficient as I understand it, and i trying to change it to make it more efficient.
text.replace(/.{4}$/,'*');
Unfortunately the result is not i expected and also it need to be hardcode the length of 4 counting from behind, which it wont work if the word's length is different.
Is there any regex method that able to replace all other character to asterisk after certain length of character (in this case is 3).
Any help to this will be appreciated. Thanks.
Edited:
As conclusion of the suggestion and discussion
Alternative way to solve the problem, which giving the almost identical result as my solution.
text.replace(/(\w{3}).*/g, "$1"+(new Array(text.length -3 + 1).join( '*' )));
by #Keerthana Prabhakaran
text.replace(new RegExp(".(?=.{0," + (text.length-4) + "}$)", "g"), '*')
by #Wiktor Stribiżew
var longerThanNeeded = "***************************";
var newText = text.substring(0,3) + longerThanNeeded.substring(0,text.length-3);
by #matthewninja
(^.{3}).|. and replace w/ \1*
by #alpha bravo
As discuss with some of the people, due to the efficiency of the code are almost the same even for the original code that I make of. Therefore it stated as side discussing.
Appreciated the helps once again.
I hope I'm not overthinking this.
text.substring(3).replace(/\S/g,'*'); has linear time complexity O(n) and isn't terribly inefficient.
I initially thought of using Array.prototype.join() like so:
var newText = text.substring(0,3) + Array(text.length-2).join("*");
Before realizing that .join() needs to run for every element of the array, which results in linear time complexity, just like your original solution. This wouldn't improve the solution at all; All I've done is inflate the space complexity.
I then went on to think of creating the element to be joined by copying and increasing the size of the prior element, which would get us down to 0(log n) complexity.
Finally, I saw the most obvious solution.
var longerThanNeeded = "***************************";
var newText = text.substring(0,3) + longerThanNeeded.substring(0,text.length-3);
which will run in constant time.
You could use this pattern (^.{3}).|. and replace w/ \1* Demo
(Please note limitation for strings less than 3 characters in length)
( # Capturing Group (1)
^ # Start of string/line
. # Any character except line break
{3} # (repeated {3} times)
) # End of Capturing Group (1)
. # Any character except line break
| # OR
. # Any character except line break
You may use
s.replace(new RegExp(".(?=.{0," + (s.length-4) + "}$)", "g"), '*')
See a JS demo:
var text = 'ABCDEFG';
var threshold = 3; // Start replacing with * after this value
if (text.length > threshold) {
text = text.replace(new RegExp(".(?=.{0," + (text.length-threshold-1) + "}$)", "g"), '*');
}
console.log(text);
Here, if threshold is 3, the pattern will look like .(?=.{0,3}$): it matches any char but a line break char with . that is followed with 0 to 3 chars other than line break chars (.{0,3}) and the end of string position ($). The (?=...) is a positive lookahead that only checks for the pattern match, but does not move the regex index and does not add the matched text to the match value (allowing subsequent consecutive symbol check).
To enable matching line breaks, replace . with [^] or [\s\S].

Capturing parentheses - /(\d)/ ? or /\s*;\s*/?

I am reading about split and below is a variable looking at the string values. However I do not understand what the symbols are looking for.
According to the page: If separator contains capturing parentheses, matched results are returned in the array.
var myString = 'Hello 1 word. Sentence number 2.';
var splits = myString.split(/(\d)/);
console.log(splits);
// Results
[ "Hello ", "1", " word. Sentence number ", "2", "." ]
My question is, what is happening here? Parentheses "(" or ")" is not part of the string. Why is space or "." separated for some and not the other?
Another one is /\s*;\s*
States it removes semi-colon before and after if there are 0 or more space. Does this mean /\s* mean it looks for a space and remove and ';' in this case is the separator?
var names = 'Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ;Chris Hand ';
console.log(names);
var re = /\s*;\s*/;
var nameList = names.split(re);
console.log(nameList);
// Results
["Harry Trump", "Fred Barney", "Helen Rigby", "Bill Abel", "Chris Hand "]
If so why doesn't /\s*^\s*/ remobe space before and after ^ symbol if my string looked like this.
var names = 'Harry Trump ^Fred Barney^ Helen Rigby ^ Bill Abel ^Chris Hand ';
console.log(names);
var re = /\s*^\s*/;
var nameList = names.split(re);
console.log(nameList);
I would like to know what the symbols mean and why they are in certain order. Thanks you.
It seems you got your examples from here.
First let's look at this one /(\d)/.
Working inside out, recognize that \d escapes all digits.
Now, from the article, wrapping the parentheses around the escape tells the split method to keep the delimiter (which in this case is any digit) in the returned array. Notice that without the parentheses, the returned array wouldn't have numeric elements (as strings of course). Lastly, it is wrapped in slashes (//) to create a regular expression. Basically this case says: split the string by digits and keep the digits in the returned array.
The second case /\s*;\s* is a little more complicated and will take some understanding of regular expressions. First note that \s escapes a space. In regular expressions, a character c followed by a * says 'look for 0 or more of c, in consecutive order'. So this regular expression matches strings like ' ; ', ';', etc (I added the single quotes to show the spaces). Note that in this case, we don't have parentheses, so the semicolons will be excluded from the returned array.
If you're still stuck, I'd suggest reading about regular expressions and practice writing them. This website is great, just be be weary of the fact that regular expressions on that site may be slightly different than those used in javascript in terms of syntax.
The 1st example below splits the input string at any digit, keeping the delimiter (i.e. the digit) in the final array.
The 2nd example below shows that leaving the parentheses out still splits the array at any digit, but those digit delimiters are not included in the final array.
The 3rd example below splits the input string any time the following pattern is encountered: as many consecutive spaces as possible (including none) immediately followed by a semi-colon immediately followed by as many consecutive spaces as possible (including none).
The 4th example below shows that you can indeed split a similar input string as in the 3rd example but with "^" replacing ";". However, because the "^" by itself means "the start of the string" you have to tell JavaScript to find the actual "^" by putting a backslash (i.e. a special indicator designated for this purpose) right in front of it, i.e. "\^".
const show = (msg) => {console.log(JSON.stringify(msg));};
var myString = 'Hello 1 word. Sentence number 2.';
var splits1 = myString.split(/(\d)/);
show(splits1);
var splits2 = myString.split(/\d/);
show(splits2);
var names1 = 'Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ;Chris Hand ';
var nameList1 = names1.split(/\s*;\s*/);
show(nameList1);
var names2 = 'Harry Trump ^Fred Barney^ Helen Rigby ^ Bill Abel ^Chris Hand ';
var nameList2 = names2.split(/\s*\^\s*/);
show(nameList2);

JavaScript's negative look-ahead doesn't work as expected?

I have some data in a textarea :
(yes it is multiline)
"#ObjectTypeID", DbType.In
"#ObjectID", DbType.Int32,
"#ClaimReasonID", DbType.I
"#ClaimReasonDetails", DbTy
"#AccidendDate", DbType.Da
"#AccidendPlaceID", DbType
"#AccidendPlaceDetails", Db
"#TypeOfMedicalTreatment",
"#MedicalTreatmentDate", Db
"#CreatedBy", DbType.Int32
"#Member_ID", DbType.Strin
.ExecuteScalar(command).ToS
In each row - I want to remove those sections : (from " (include) till the end of row) :
Visually : ( I sampled only 4 )
I've managed to do this :
value=value.replace(/\"[a-z,. ]+(?!.*\")/gi,'')
Which means : search the first " where have charters after it , which doesnot have a future "
This will yield the required results :
"#ObjectTypeID
"#ObjectID32,
"#ClaimReasonID
"#ClaimReasonDetails
"#AccidendDate
"#AccidendPlaceID
"#AccidendPlaceDetails
"#TypeOfMedicalTreatment
"#MedicalTreatmentDate
"#CreatedBy32
"#Member_ID
.ExecuteScalar(command).ToS
Question:
I understand why it is working , but I dont understand why the following is not working :
value=value.replace(/\".+(?!.*\")/gi,'')
http://jsbin.com/fanep/4/edit
I mean : it suppose to search " where has charters after it , which doesn't has future " ....
What am I missing ? I really hate to declare [a-z,. ]
+ is greedy. Since "the whole thing" matches your rule of "must not have a " after", it will go with that.
The reason your first regex works is because you are disallowing most characters by explicitly whitelisting certain ones.
To fix, try adding ? after the + - this will make it lazy instead, matching as little as possible while still meeting the rules.
Additionally, you are searching for the stuff you want to keep... and then deleting it.
Try this instead:
val = val.replace(/"[^"]*(?=[\r\n]|$)/g,'');
This will remove everything from the last " to the end of a line (or end of the input).
value=value.replace(/\"[a-z,. ]+(?!.*\")/gi,'')
means: search the first " where have charters after it, which doesnot have a future "
To be exact: It matches the first " that has some of the characters [a-z,. ] after it, which then is not (in any distance) followed by another ".
I dont understand why the following is not working:
value=value.replace(/\".+(?!.*\")/gi,'')
You have removed the restriction of the character class. .+ will now match any char, including quotes. Regardless whether greedy or not, it will now find the first " that is followed by an amount of any characters (including other quotes) that are no more followed by quotes - i.e. it will suffice if .+ matches until the last quote.
I really hate to declare [a-z,. ]
You can just use the class of all characters except quotes: [^"]. Indeed, I think the following lookahead-free version matches your intent better:
value = value.replace(/"[^"\n\r]*/gi, '');
The one that doesn't work fails because the .+ is greedy. It eats up all it can. (Visual tools can help here, such as this one: http://regex101.com/r/eJ5kJ2/1) We can make it clearer that .+ is matching too much by putting it in a capture group: http://regex101.com/r/qF7nR9/1 Which show us:
In your one that does work (http://regex101.com/r/kR8vL6/1), you've changed that to [a-z,. ]+, which means "one or more a to z, comma, period, or space" (note that the . there is just a period, not a wildcard). That's much more limited (in particular, it doesn't include #).
Side note: There's no need to escape the " with a backslash, " isn't a special character in regular expressions.
Why the below regex is not working?
\".+(?!.*\")
Answer:
\" matches the first " and the following .+ would match greedily upto the last character. Because the last character in a line isn't followed by any character zero or more times plus \, the above regex would match the whole line undoubtably.
For your case, you could simply use the below regex to match from the second " upto the end of the line anchor.
\"[^"\n]*$
DEMO

Delete a string in javascript, without leaving an empty space?

I've seen multiple instance of that kind of question, but not the one I'm looking for specifically... (I just hope I'm not hopelessly blind ! :P)
Let's consider this code:
var oneString = "This is a string";
document.write(oneString.replace("is", ""));
I would have assumed that the output would have been:
This a string.
But this is the output I'm getting:
This a string
It's like replace() think that the second argument sent is " " and not ""... What would be the proper manner then to strip the string of a given string, without having extra spaces floating in my output ?
You are actually getting "is" replaced with an empty string, it's the space before and after the "is" you replace that stay around as the two spaces you see. Try;
oneString.replace("is ", "")
Are you sure you're not getting "This a string"?
I think you should replace "is " with "" to get your desired output. There is a space before as well as after the word.
Look at the original string - "This_is_a_string" (I replaced spaces with underscores). When you remove "is", you don't touch either of the surrounding spaces, so both end up in the output. What you need to do is oneString.replace("is","").replace(/ +/," ") -- get rid of "is" and then eliminate any double spaces. If you want to keep some double spaces, try oneString.replace(" is","") instead, though you will run into issues if the string starts with is (eg "is it safe?").
The best answer might be something like oneString.replace(/is ?/,"") to match is possibly followed by a space oroneString.replace(/ ?is ?/," ") to match is possibly surrounded by spaces, and replace all of them with one space.
You didn't include any spaces in your pattern. When I try your code in Chrome I get:
> "This is a string".replace("is","")
"Th is a string"
One way to accomplish what you're trying would be to use a regexp instead:
> "This is a string".replace(/is\s/,"")
"This a string"
var aString = "This is a string";
var find = "is"; // or 'This' or 'string'
aString = aString.replace(new RegExp("(^|\\s+)" + find + "(\\s+|$)", "g"), "$1");
console.log(oneString);
The only case where this isn't perfect is when you replace the last word in the sentence. It will leave one space at the end, but I suppose you could check for that.
The g modifier is to make the replace replace all instances, and not just the first one.
Add the i modifier to make it case insensitive.
If you also want this to work on strings like:
"This has a comma, in it"
Change the regexp to:
var find = "comma";
new RegExp("(^|\\s+)" + find + "(\\s+|$|,)", "g")

Categories