regex - ignore whitespace from the beginning of the string - javascript

I have to validate a string into the jquery textcomplete.
Now my strings are arragned on multiple lines, a single line may have a couple key = value or multiple separated by commas
like:
key1=value1, mkey2 = value2;
input3 = value3
The expression I need must match the left operand of the expression
What I did:
/(?:,\s*|^\s|^|,)(?:\s*)([^=]\w*)/
My issue is that it instead of just returning
"key1" "mkey2" "input3"
it returns
["key1", "key1"], [", mkey2", "mkey2"] , [" input3", "input3"]
But I'm expecting (actually jQuery.textcomplete is expecting)
["key1"], ["mkey2"] , ["input3"]
JSFIDDLE
EDIT: JS Code (previously was only on jfiddle)
var items = [
"key_1",
"key_2",
"key",
"halt",
"keybone",
"klingon",
"kabum"
];
$('#myTextArea1').textcomplete(
[{
match: /[^=](\w*)$/,
index: 1, // default = 2
search: function (term, callback) {
term = term.toLowerCase();
callback($.map(items, function (item) {
return item.toLowerCase().indexOf(term) >= 0 ? item : null;
}));
},
replace: function (item) {
return '' + item + ' = ';
}
}]);

I'm not sure how you're calling it, but try this out:
\s*(\w+)\s*=

This is the RegEx I was looking for:
/(?<=^|,\s|,)(\w+(?=[=]|$))/m
What does it do?
• (?<=^|,\s|,) is a lookbehind that checks if the string is the beginning ^, is , or ,
• (\w+(?=[=]|$)) could be decomposed in two sub-expressions:
<> \w+ that matches a word of at least a letter or digit POSIX [:alnum:] is not supported in JS
<> (?=[=]|$) is a lookahead that keeps the expression only if we're at the end of text $ or the next character is not a =

Related

How to replace all values in an object with strings using JS?

I'm trying to get an array of JSON objects. To do that, I'm trying to make the input I have parsable, then parse it and push it to that array using a for loop. The inputs I have to work with look like this:
firstname: Chris, lastname: Cheshire, email: chris#cmdcheshire.com, viewerlink: audiencematic.com/viewer?v\u003dTESTSHOW\u0026push\u003d8A043B5A, tempid: 8A043B5A, permaid: F8tGYNx, showid: TESTSHOW
I've gotten it to the point where each loop produces something like this:
{ "firstname": First Name, "lastname": Last Name, "email": sample#gmail.com, "viewerlink": audiencematic.com/viewer?v=TESTSHOW&push=715B3074, "tempid": 715B3074, "permaid": F8tGYNx, "showid": TESTSHOW }
But got stuck on the last bit, making the values strings. I want it to look like this, so I can use JSON.parse():
{ "firstname": "First Name", "lastname": "Last Name", "email": "sample#gmail.com", "viewerlink": "audiencematic.com/viewer?v=TESTSHOW&push=715B3074", "tempid": "715B3074", "permaid": "F8tGYNx", "showed": "TESTSHOW" }
I tried a couple of different methods I found on here, but one of the values is a URL and the period is screwing with the replace expressions. I tried using the replace function like this:
var jsonStr2 = jsonStr.replace(/(: +\w)|(:+\w)/g, function(matchedStr) {
return ':"' + matchedStr.substring(2, matchedStr.length) + '"';
});
But it just becomes this:
{ "firstname":""irst Name, "lastname":""ast Name, "email":""ample#gmail.com, "viewerlink":""udiencematic.com/viewer?v=TESTSHOW&push=715B3074, "tempid":""15B3074, "permaid":""8tGYNx, "showid":""ESTSHOW }
How should I change my replace function?
(I tried that code because I'm using
var jsonStr = string.replace(/(\w+:)|(\w+ :)/g, function(matchedStr) {
return '"' + matchedStr.substring(0, matchedStr.length - 1) + '":';
});
to put parenthesis around the key sides and that seems to work.)
FIGURED IT OUT!! SEE MY ANSWER BELOW.
One option might be to try using a deserialized version of the string, alter the values associated with the properties of the object, and then convert back to a string.
var person = "{fname:\"John\", lname:\"Doe\", age:25}";
var obj = JSON.parse(person);
for (x in obj) {
obj[x] = "";
}
var result = JSON.stringify(obj);
It's a little longer than doing a string replacement, but I find it a little easier to follow.
I figured it out! I just had to mess around in regexr to figure out what conditions I needed. Here's the working for loop code:
for (i = 0; i < audiencelistdirty.feed.openSearch$totalResults.$t; i++) {
var string = '{ ' + audiencelistdirty.feed.entry[i].content.$t + ' }';
var jsonStr = string.replace(/(\w+:)|(\w+ :)/g, function(matchedStr) {
return '"' + matchedStr.substring(0, matchedStr.length - 1) + '":';
});
var jsonStr1 = jsonStr.replace(/(:(.*?),)|(:\s(.*?)\s)/g, function(matchedStr) {
return ':"' + matchedStr.substring(2, matchedStr.length - 1) + '",';
});
var jsonStr2 = jsonStr1.replace(/(",})/g, function(matchedStr) {
return '" }';
});
var newObj = JSON.parse(jsonStr2);
audiencelist.push(newObj);
};
It's pretty ugly but it works.
EDIT: Sorry, I completely misread the question. To replace the values with quoted strings use this regex replace function:
const str =
'firstname: Chris, lastname: Cheshire, email: chris#cmdcheshire.com, viewerlink: audiencematic.com/viewer?v\u003dTESTSHOW\u0026push\u003d8A043B5A, tempid: 8A043B5A, permaid: F8tGYNx, showid: TESTSHOW'
const json = (() => {
const result = str
.replace(/\w+:\s(.*?)(?:,|$)/g, function (match, subStr) {
return match.replace(subStr, `"${subStr}"`)
})
.replace(/(\w+):/g, function (match, subStr) {
return match.replace(subStr, `"${subStr}"`)
})
return '{' + result + '}'
})()
Wrap the input string into commas then use a regex to identify the keys (between , and :) and their associated values (between : and ,) and construct the object directly as in the example below:
const input = ' firstname : Chris , lastname: Cheshire, email: chris#cmdcheshire.com, viewerlink: audiencematic.com/viewer?v\u003dTESTSHOW\u0026push\u003d8A043B5A, tempid: 8A043B5A, permaid: F8tGYNx, showid: TESTSHOW ';
const wrapped = `,${input},`;
const re = /,\s*([^:\s]*)\s*:\s*(.*?)\s*(?=,)/g;
const obj = {}
Array.from(wrapped.matchAll(re)).forEach((match) => obj[match[1]] = match[2]);
console.log(obj)
String.matchAll() is a newer function, not all JavaScript engines have implemented it yet. If you are one of the unlucky ones (or if you write code to be executed in a browser) then you can use the old-school way:
const input = ' firstname : Chris , lastname: Cheshire, email: chris#cmdcheshire.com, viewerlink: audiencematic.com/viewer?v\u003dTESTSHOW\u0026push\u003d8A043B5A, tempid: 8A043B5A, permaid: F8tGYNx, showid: TESTSHOW ';
const wrapped = `,${input},`;
const re = /,\s*([^:\s]*)\s*:\s*(.*?)\s*(?=,)/g;
const obj = {}
let match = re.exec(wrapped);
while (match) {
obj[match[1]] = match[2];
match = re.exec(wrapped);
}
console.log(obj);
The anatomy of the regex used above
The regular expression piece by piece:
/ # regex delimiter; not part of the regex but JavaScript syntax
, # match a comma
\s # match a white space character (space, tab, new line)
* # the previous symbol zero or more times
( # start the first capturing group; does not match anything
[ # start a character class...
^ # ... that matches any character not listed inside the class
: # ... i.e. any character but semicolon...
\s # ... and white space character
] # end of the character class; the entire class matches only one character
* # the previous symbol zero or more times
) # end of the first capturing group; does not match anything
\s*:\s* # zero or more spaces before and after the semicolon
( # start of the second capturing group
.* # any character, any number of times; this is greedy by default
? # make it not greedy
) # end of the second capturing group
\s* # zero or more spaces
(?= # lookahead positive assertion; matches but does not consume the matched substring
, # matches a comma
) # end of the assertion
/ # regex delimiter; not part of the regex but JavaScript
g # regex flag; 'g' for 'global' is needed to find all matches
Read about the syntax of regular expressions in JavaScript. For a more comprehensive description of the regex patterns I recommend reading the PHP documentation of PCRE (Perl-Compatible Regular Expressions).
You can see the regex in action and play with it on regex101.com.

why condition is always true in javascript?

Could you please tell me why my condition is always true? I am trying to validate my value using regex.i have few conditions
Name should not contain test "text"
Name should not contain three consecutive characters example "abc" , "pqr" ,"xyz"
Name should not contain the same character three times example "aaa", "ccc" ,"zzz"
I do like this
https://jsfiddle.net/aoerLqkz/2/
var val = 'ab dd'
if (/test|[^a-z]|(.)\1\1|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz/i.test(val)) {
alert( 'match')
} else {
alert( 'false')
}
I tested my code with the following string and getting an unexpected result
input string "abc" : output fine :: "match"
input string "aaa" : output fine :: "match"
input string "aa a" : **output ** :: "match" why it is match ?? there is space between them why it matched ????
input string "sa c" : **output ** :: "match" why it is match ?? there is different string and space between them ????
The string sa c includes a space, the pattern [^a-z] (not a to z) matches the space.
Possibly you want to use ^ and $ so your pattern also matches the start and end of the string instead of looking for a match anywhere inside it.
there is space between them why it matched ????
Because of the [^a-z] part of your regular expression, which matches the space:
> /[^a-z]/i.test('aa a');
true
The issue is the [^a-z]. This means that any string that has a non-letter character anywhere in it will be a match. In your example, it is matching the space character.
The solution? Simply remove |[^a-z]. Without it, your regex meets all three criteria.
test checks if the value contains the word 'test'.
abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz checks if the value contains three sequential letters.
(.)\1\1 checks if any character is repeated three times.
Complete regex:
/test|(.)\1\1|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz/i`
I find it helpful to use a regex tester, like https://www.regexpal.com/, when writing regular expressions.
NOTE: I am assuming that the second criteria actually means "three consecutive letters", not "three consecutive characters" as it is written. If that is not true, then your regex doesn't meet the second criteria, since it only checks for three consecutive letters.
I would not do this with regular expresions, this expresion will always get more complicated and you have not the possibilities you had if you programmed this.
The rules you said suggest the concept of string derivative. The derivative of a string is the distance between each succesive character. It is specially useful dealing with password security checking and string variation in general.
const derivative = (str) => {
const result = [];
for(let i=1; i<str.length; i++){
result.push(str.charCodeAt(i) - str.charCodeAt(i-1));
}
return result;
};
//these strings have the same derivative: [0,0,0,0]
console.log(derivative('aaaaa'));
console.log(derivative('bbbbb'));
//these strings also have the same derivative: [1,1,1,1]
console.log(derivative('abcde'));
console.log(derivative('mnopq'));
//up and down: [1,-1, 1,-1, 1]
console.log(derivative('ababa'));
With this in mind you can apply your each of your rules to each string.
// Rules:
// 1. Name should not contain test "text"
// 2. Name should not contain three consecutive characters example "abc" , "pqr" ,"xyz"
// 3. Name should not contain the same character three times example "aaa", "ccc" ,"zzz"
const derivative = (str) => {
const result = [];
for(let i=1; i<str.length; i++){
result.push(str.charCodeAt(i) - str.charCodeAt(i-1));
}
return result;
};
const arrayContains = (master, sub) =>
master.join(",").indexOf( sub.join( "," ) ) == -1;
const rule1 = (text) => !text.includes('text');
const rule2 = (text) => !arrayContains(derivative(text),[1,1]);
const rule3 = (text) => !arrayContains(derivative(text),[0,0]);
const testing = [
"smthing textual",'abc','aaa','xyz','12345',
'1111','12abb', 'goodbcd', 'weeell'
];
const results = testing.map((input)=>
[input, rule1(input), rule2(input), rule3(input)]);
console.log(results);
Based on the 3 conditions in the post, the following regex should work.
Regex: ^(?:(?!test|([a-z])\1\1|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz).)*$
Demo

I need to take an inputted string, take the non-numeric characters out, and then if the string begins with a 1, remove the 1

function changeNumber(e) {
var phoneNumber = e.replace(/\D/g, '');
if (phoneNumber.startsWith("1")) {
var finalNumber = phoneNumber.slice(0);
return finalNumber;
} else {
return phoneNumber;
};
};
console.log(changeNumber("+1 (234)-567.8995"));
Desired result should be: 2345678995 but I am getting 12345678995. It's like it's not running through the if statement.
You need to use String#slice starting from index 1, because you want to omit the first character at index 0.
phoneNumber.slice(0)
returns a copy of the string, as an assignment of the variable, but
phoneNumber.slice(1)
returns the string from index 1 and all following characters.
function changeNumber(e) {
var phoneNumber = e.replace(/\D/g, '');
return phoneNumber.startsWith("1")
? phoneNumber.slice(1)
: phoneNumber;
}
console.log(changeNumber("+1 (234)-567.8995"));
Made a more concise function without conditionals
\D matches all non-digit characters.
^1 matches 1 if it is the first character in the string.
function changeNumber(e) {
return e.replace(/\D/g, '').replace(/^1/g, '');
};
console.log(changeNumber("+1 (234)-567.8995"));

Removing every non-digit character except a plus (+) sign in phone number

I want to alter a text string with a regular expression, removing every non-digit character, except a + sign. But only if it's the first character
+23423424dfgdgf234 --> +23423424234
2344 234fsdf 9 --> 23442349
4+4 --> 44
etc
The replacing of 'everything but' is pretty simple:
/[^\+|\d]/gi but that also removes the +-sign as a first character.
how can I alter the regexp to get what I want?
If it matters: I'm using the regexp in javascript's str.replace() function.
I would do it in two steps, first removing everything that must be removed apart the +, then the + that aren't the first char :
var str2 = str1.replace(/[^\d\+]+/g,'').replace(/(.)\++/g,"$1")
You'd have to do this in two steps:
// pass one - remove all non-digits or plus
var p1 = str.replace(/[^\d+]+/g, '');
// remove plus if not first
var p2 = p1.length ? p1[0] + p1.substr(1).replace(/\+/g, '') : '';
console.log(p2);
You can replace the following regex
[^\d+] with ''
and then on the resulting string, replace
(.)\+ with '$1'
Demo: http://regex101.com/r/eT6uF6
Updated: http://jsfiddle.net/QVd7R/2/
You could combine the above suggested 2 replaces in a single RegExp:
var numberWithSign = /(^\+)|[^\d]+/g;
var tests =
[
{"input" : "+23423424dfgdgf234", "output" : "+23423424234"},
{"input" : "2344 234fsdf 9" , "output" : "23442349"},
{"input" : "4+4" , "output" : "44"},
{"input" : "+a+4" , "output" : "+4"},
{"input" : "+a+b" , "output" : "+"},
{"input" : "++12" , "output" : "+12"}
];
var result = true;
for (index in tests) {
var test = tests[index];
testResult = test.input.replace(numberWithSign,"$1");
result = result && (testResult == test.output);
if (!result) {
return testResult + "\n" + test.output;
}
}
return result;
Basically the first part (^\+) would match only the + sign in the beginning of the line, and will put it as $1, so when you replace this match with $1 it will keep the plus sign in the beginning of the string. If it does not match, then the next part of the regexp [^\d]+ will take effect, replacing all non-digits with an empty string (as there would be nothing in the value of $1)
Try this:
var newString = Yourstring.match(/(^\+)?\d*/g).join("");

How to insert the parentheses and values if missing string?

Here i have group of string with comma, like "stack,flow(2),over(4),temp(0)" if just string without open and close parentheses value, i need to insert the with (1). stack(1).
Expected scenario :
1.insert (1) missing open & close parentheses
2.within parentheses should be >0 numeric values.
3.within parentheses if any alpha character , show error message.
As i need to validate that with in parentheses value should be numberic. I have tried the some scenrio, but i need help to insert (1).
function testCases(str){
return (
str.match(new RegExp("\\([^,]+\\)","g")).length == str.split(",").length
);
}
Here is jsfiddle
If I correctly understand you want to insert (1) before the comma if there's no parenthesized group, then you can do this :
var str = "stack,flow(2),over(4),temp(0)";
str = str.replace(/([^)]),/g, "$1(1),");
Result : "stack(1),flow(2),over(4),temp(0)"
If you also want to ensure the group contains a strictly positive integer, you may do
var str = "stack,flow(2),flow(k),over(4),neg(-3),temp(0)";
str = str.split(',').map(function(s){
return s.replace(/(\((.*?)\))?$/, function(s,d,e) {
return '('+ (e>0?e:1)+')'
})
}).join(',');
Result : "stack(1),flow(2),flow(1),over(4),neg(1),temp(1)"
well, my solution is a little complicated, but more relatable, e.g. it works for:
stacka(z),flow(2),over(4),temp(0),ccc
Here the code:
function convert(str) {
//ends with (num)
var regexObj = /\(\d+\)$/;
return str.split(',').map(function(p) {
return p + (regexObj.test(p) ? '' : '(1)');
}).join(',');
}
http://jsfiddle.net/rooseve/pU2Q7/

Categories

Resources