Part of the string is missing when trying to replace - javascript

I have a string that looks like this:
[TITLE|prefix=X|suffix=a] [STORENAME|prefix=b] [DYNAMIC|limit=10|seperator=-|random=1|reverse=1|prefix=c]
I would like to replace the values of all prefix attributes with hello. So the goal is that the string looks like this:
[TITLE|prefix=hello|suffix=a] [STORENAME|prefix=hello] [DYNAMIC|limit=10|seperator=-|random=1|reverse=1|prefix=hello]
This is what I have tried:
const obj = {};
obj.prefix = "[TITLE|prefix=a|suffix=x] [STORENAME|prefix=b] [DYNAMIC|limit=10|seperator=-|random=1|reverse=1|prefix=c]";
function replace(search, replace) {
const regex = new RegExp(`(?<=\\[${search}\\|[^\\]]*${replace}=)[^|\\]]+`);
obj.prefix = obj.prefix.replace(regex, 'hello');
}
replace('TITLE', 'prefix');
replace('STORENAME', 'prefix');
replace('DYNAMIC', 'prefix');
console.log(obj.prefix);
As you see it works fine!
I have used almost the same code for my project but it fails. You can check my project on JSFiddle. Just type anything on an input field and check the console. You will see that the value of first prefix will be changed but 2 further prefix attributes are missing.
So this is what I get:
[TITLE|prefix=anything|suffix=a] [STORENAME] [DYNAMIC|limit=10|seperator=-|random=1|reverse=1]
And this is what I should get:
[TITLE|prefix=anything|suffix=a] [STORENAME|prefix=another thing] [DYNAMIC|limit=10|seperator=-|random=1|reverse=1|prefix=one more thing]
What is the reason that those attributes are missing?
Update
If I am not mistaking, my main problem is the if-statement:
if (mtPr.query[mtPr.settings.activeLang].includes(replace)) {
With this if-statement, I would like to check if either TITLE has the attribute prefix or STORENAME has the attribute prefix or DYNAMIC has the attribute prefix. But this is a bad workaround since the value of replace is always prefix (see line numbers 241, 245 and 251). And since we already have prefix in the WHOLE string, it means that we're caught in that if-statement every single time. So a possible solution could be, checking if the parameter replace is included AND does it belong to the parameter search.

Try this
function replace(search, replace) {
const regex = new RegExp(`(${search}[^\\[\\]]*\\|prefix\\=)[^\\|\\[\\]]+`);
obj.prefix = obj.prefix.replace(regex, '$1hello');
}

As I have described in my question, the problem was really the if-statement. This how I could resolve it:
const searchMatchesReplace = new RegExp(`(?<=${search}.+${replace}=)[^\\]|]+`);
if (searchMatchesReplace.test(mtPr.query[mtPr.settings.activeLang])) {
const regex = new RegExp(`(?<=\\[${search}\\|[^\\]]*${replace}=)[^|\\]]+`, 'g');
result = mtPr.query[mtPr.settings.activeLang].replace(regex, value);
}
// Replace parameters if they do not exist
else {
const regex = new RegExp(`(\\[${search}(?:\\|[^\\][]*)?)]`, 'gi');
result = mtPr.query[mtPr.settings.activeLang].replace(regex, `$1|${replace}=${value}]`);
}

Related

Extract string from two identical symbols javascript

suppose I have a string :
I want to replace the above string as:
For this i tried as:
var result=[];
result=string.split("+");
console.log(result[1]);
It gives o/p: details.data
Now to replace the said part I tried as:
var res = string1.replace("+details.data+", ''+result[1]+'');
But it gives me o/p as: hello someting "+details.data+" still something
I want to replace exactly in the attachment.
Is there any other way to achieve this?
Can't you use: str.replace("+details.data+", `\`+${result[1]}+\``) ?
This way you are replacing the string with a template literal which includes the result (evaluated to a string). It also includes the backticks in the string by escaping them with backslashes.
I believe what you're trying to achieve is this:
let string1 = "hello something +details.data+ hello something";
const result = ['data', 'yay! My data is here'];
const updatedString = string1.replace('+details.data+', `+${result[1]}+`);
console.log(updatedString);
By using a template literal we can easily replace the details.data with the result data.
Assuming that you want to replace +details.data+ with the actual value of details.data
You need something like this:
var details = { data: 'blabla' }
const string = `hello something "+details.data+" still something`;
string = string.replace('+details.data+', details.data);
console.log(string); // hello something "blabla" still something
If you wanted this to be dynamic you would need the details object as a prop of another object:
var obj = { details: { data: 'blabla' }}
var arr = string.split('+'); // ['hello something "','details.data','" still something']
var path = arr[1].split('.'); // ['details', 'data']
// you would need some logic here to check that each of the props from path exists in obj
var value = obj[path[0]][path[1]];
string = string.replace('+details.data+', value);
console.log(string);

if statement on template literal value

I am trying to do the following with no avail: There are a few scenarios where self.name has a erroneous '/' in the middle of the value; ie. populating as such 'WSDH/222-310' - I am trying to simply catch this and convert it for the value to resolve in my following .load call as 'WSDH-222-310'
if (self.type === "car") {
var carClean = ${self.name}; // returns syntax error
var res = str.replace("/", "-");
console.log(carClean )
console.log(res)
// console.log({self.type});
}
self.$container.load(`view/coolObjects/${self.type}/${self.name}`, loadProfile);
I think there's a use case for a tagged template if all embedded variables should be escaped.
A more advanced form of template literals are tagged templates. Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions. In the end, your function can return your manipulated string
Example:
var path = `foo/${x}/${y}/bar`;
If both x and y should be escaped so as to replace '/' with '-', then you could do this:
const sanitize_path = (strings, ...parts) =>
strings
.flatMap((str, idx) =>
[ str,
idx < parts.length
? parts[idx].replace(/\//g, '-')
: '' ])
.join('');
const x = '1/2/3';
const y = 'y';
console.log(
sanitize_path`foo/${x}/${y}/bar`
);
Why bother cleaning the strings before using them?
I'm not clear on exactly what you're trying to do, but you can "clean" on the fly like this:
self.$container.load(`view/coolObjects/${self.type}/${self.name.replace("/","-")}`, loadProfile);
Whether or not your surrounding code works, I can't tell. But here's a working sample of what I'm suggesting:
let self = {"type":"mytype","name":"myname"};
console.log(`view/coolObjects/${self.type}/${self.name.replace("my","your")}`);
If I understand your question correctly then you're on the right track using String.prototype.replace - should be something simple as this:
var self = {
name: 'WSDH/222-310'
};
self.name = self.name.replace('/', '-');
console.dir(self);

string parsing {{var}}/text{{var}}

I need parse follow string const input = '{{var}}/text{{var}}' result must be follow
const result = ['{{var}}', '/text', '{{var}}']. Thanks
You will need a function to replace the text but i think the regex you want is ({{\w+}})(\/\w+)({{\w+}}). This provides the parts in the groups 1-3 so you can format them how you like. You probably also want to add a check to make sure part 1 is the same as part 3 to avoid mismatched pairs.
function replace(str) {
let matches = str.match(/({{\w+}})(\/\w+)({{\w+}})/);
return str.replace(/({{\w+}})(\/\w+)({{\w+}})/, `['${matches[1]}', '${matches[2]}', '${matches[3]}']`);
}
replace("const input = '{{var}}/text{{var}}'"); // "const input = '['{{var}}', '/text', '{{var}}']'"

Matching css selectors with RegExp doesn't work in browser

I try to match css selectors as can be seen here:
https://regex101.com/r/kI3rW9/1
. It matches the teststring as desired, however when loading a .js file to test it in the browser it fails both in firefox and chrome.
The .js file:
window.onload = function() {
main();
}
main = function() {
var regexSel = new RegExp('([\.|#][a-zA-Z][a-zA-Z0-9.:_-]*) ?','g');
var text = "#left_nav .buildings #rfgerf .rtrgrgwr .rtwett.ww-w .tw:ffwwwe";
console.log(regexSel.exec(text));
}
In the browser it returns:["#left_nav ", "#left_nav", index: 0, input: "#left_nav .buildings #rfgerf .rtrgrgwr .rtwett.ww-w .tw:ffwwwe"]
So it appears it only captures the first selector with and without the whitespace, despite the whitespace beeing outside the () and the global flag set.
Edit:
So either looping over RegExp.exec(text) or just using String.match(str) will lead to the correct solution. Thanks to Wiktor's answer i was able to implement a convenient way of calling this functionality:
function Selector(str){
this.str = str;
}
with(Selector.prototype = new String()){
toString = valueOf = function () {
return this.str;
};
}
Selector.prototype.constructor = Selector;
Selector.prototype.parse = function() {
return this.match(/([\.|#][a-zA-Z][a-zA-Z0-9.:_-]*) ?/g);
}
//Using it the following way:
var text = new Selector("#left_nav .buildings #rfgerf .rtrgrgwr .rtwett.ww-w .tw:ffwwwe");
console.log(text.parse());
I decided however using
/([\.|#][a-zA-Z][a-zA-Z0-9.:_-]*) ?/g over the suggested
/([.#][a-zA-Z][a-zA-Z0-9.:_-]*)(?!\S)/g because it matches with 44 vs. 60 steps on regex101.com on my teststring.
You ran exec once, so you got one match object. You'd need to run it inside a loop.
var regexSel = new RegExp('([\.|#][a-zA-Z][a-zA-Z0-9.:_-]*) ?','g');
var text = "#left_nav .buildings #rfgerf .rtrgrgwr .rtwett.ww-w .tw:ffwwwe";
while((m=regexSel.exec(text)) !== null) {
console.log(m[1]);
}
A regex with a (?!\S) lookaround at the end (that fails the match if there is no non-whitespace after your main consuming pattern) will allow simpler code:
var text = "#left_nav .buildings #rfgerf .rtrgrgwr .rtwett.ww-w .tw:ffwwwe";
console.log(text.match(/[.#][a-zA-Z][a-zA-Z0-9.:_-]*(?!\S)/g));
Note that you should consider using regex literal notation when defining your static regexps. Only prefer constructor notation with RegExp when your patterns are dynamic, have some variables or too many / that you do not want to escape.
Look also at [.#]: the dot does not have to be escaped and | inside is treated as a literal pipe symbol (not alternation operator).

With JavaScript, I need help concatenating a variable into a regular expression

I'm writing a JavaScript function to extract a segment out of a URL that appears to the right of a designated segment.
For instance, if this is my URL ...
mysite.com/cat/12/dog/34?test=123
... I would like to be able to pass 'cat' to the function and get 12, and later pass 'dog' to the function and have it return 34. I found this answer on StackOverflow to extract the URL segment, but it uses a string literal. And I'm having difficulty concatenating a passed in value.
jQuery to parse our a part of a url path
Here is my code. In this, rather than hard coding 'cat' into the pattern match, I would like to pass 'cat' into the segmentName parameter and have the regular expression match on that.
var url = "www.mysite.com/cat/12/dog/34?test=123";
alert(getNextSegmentAfterSegmentName(url, 'cat'));
function getNextSegmentAfterSegmentName(currentPath, segmentName) {
var nextSegment = "";
segmentName = segmentName.toLowerCase();
//var currentPath = window.location.pathname.toLowerCase();
if (currentPath.indexOf(segmentName) >= 0) {
var path = currentPath.split('?')[0]; // Strip querystring
// How do I concatenate segmentName into this?
var matches = path.match(/\/cat\/([^\/]+)/);
if (matches) {
nextSegment = matches[1];
}
}
return nextSegment;
}
Here is a jsfiddle example:
http://jsfiddle.net/Stormjack/2Ebsv/
Thanks for your help!
You need to create a RegExp object if you want to create regex using some string variable:
path.match(new RegExp("\/" + segmentName + "\/([^\/]+)"));

Categories

Resources