reading all the submatches in regexp multiple matches - javascript

today i'm trying to parse a 'ps aux' output (issued from a node.js server)
so i made an happy regex to parse the values, and i wanted to put all those fancy informations into a simple JSON object :-)
problem is, the regex i've made has 3 match groups, doing multiple matches... and i don't even know if it's possible to have it all the matches returned.
var spawn = require("child_process").spawn;
function exec(http_req, http_resp){
var re_ps = /(?:([\d\.\w\-\?\/\+]+)\s+){8}(?:((?:\d+\:\d+)|(?:\w+\d+))\s+){2}([^\n]+)/g,
result_re_ps,
array_re_ps = [];
//[USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT], dates[START, TIME], COMMAND
var ps_process = spawn("ps", ["aux"]);
ps_process.stdout.on("data", function(data){
var split_data = data.toString().split('\n');
for (var i=1; i < 2; i++){
while ((result_re_ps = re_ps.exec(split_data[i])) != null){
console.log("--- while iteration ---");
console.dir(result_re_ps);
//console.dir(result_re_ps);
}
}
//http_resp.write(data);
});
ps_process.on("exit", function (code) {
if (code !== 0) {
console.log("ps_process exited with code " + code);
}
http_resp.end();
});
}
exports.exec = exec;
the "--- while iteration ---" it's just one per each line, instead, it should be multiples!
I will link a fancy screenshot to let you visually understand what kind of data i'm expecting
As you can see the above are 3 groups of data, each one with multiple occurrences
Any help? :p
EDITED TO CLARIFY:
This is the result of a line like:
root 5213 0.0 2.1 8688 2760 ? Ss 11:33 0:01 sshd: root#pts/0
As you can see, the resulting array is 1-dimensional, instead for the results to be contained entirely it HAS to be at least 2-dimensional
UPDATE:
For now i've solved the problem changin my code like this:
var spawn = require("child_process").spawn;
function exec(http_req, http_resp){
var array_re_ps = [];
var re_ps1 = /(?:([\d\.\w\-\?\/\+]+)\s+)/g,
re_ps2 = /(?:((?:\d+\:\d+)|(?:\w+\d+))\s+)/g,
re_ps3 = /([^\n]+)/g;
//[USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT], dates[START, TIME], COMMAND
var ps_process = spawn("ps", ["aux"]);
ps_process.stdout.on("data", function(data){
var split_data = data.toString().split('\n');
for (var i=20; i < 21; i++){
array_re_ps[0] = [], array_re_ps[1] = [];
for (var j=0; j<8; j++){
array_re_ps[0].push(re_ps1.exec(split_data[i])[1]);
}
re_ps2.lastIndex = re_ps1.lastIndex;
for (var j=0; j<2; j++){
array_re_ps[1].push(re_ps2.exec(split_data[i])[1])
}
re_ps3.lastIndex = re_ps2.lastIndex;
array_re_ps[2] = re_ps3.exec(split_data[i])[1];
console.dir(array_re_ps);
}
});
ps_process.on("exit", function (code) {
if (code !== 0) {
console.log("ps_process exited with code " + code);
}
http_resp.end();
});
}
exports.exec = exec;
Basically i split my long regexp, in 3 smaller ones, and i do cycle through their results.
If you try the code i formatted the resulting array exactly as i wanted, but i still think that it's a side-solution.
Since Regular Expressions lets you "multiple parse group multiple times", it is possible to have that functionality in javascript?

Take a look at the return values of the exec function.
It returns the index where it first matched, the original string and the capture groups in the elements [0]...[n].
All this is available in your output, you just have to iterate through the single elements of the array.

Related

Why is this for loop reverting to 0 and never getting to the end of the size of this array

This problem refers to the hackerank anagram question here:
For some reason, this for loop never completes. It gets to 3 (-2 from the length of the array it is iterating over) and then goes back to 0 and I can't tell why.
const dictionary = ['hack', 'a' , 'rank' , 'khac','ackh']
const query = ['a','nark','bs','hack','stair']
console.log(stringAnagram(dictionary, query))
function stringAnagram(dictionary, query){
let sortedDictionary=[];
let sortedQuery = [];
let alphabetisedWord;
let sortedWord;
let anagramsCount = [];
// sort them
for(let i = 0; i<dictionary.length-1; i++){
sortedWord= dictionary[i];
if(dictionary[i].length > 1){
sortedWord= sortedWord.split('');
console.log('sortedWord: ',sortedWord)
sortedWord= sortedWord.sort();
console.log('sortedWord: ',sortedWord)
sortedWord= sortedWord.join('');
console.log('sortedWord: ',sortedWord)
sortedDictionary[i] = sortedWord;
} else {
sortedDictionary[i] = sortedWord;
}
console.log(i, dictionary.length)
}
for(let i = 0; i<query.length-1; i++){
alphabetisedWord = query[i];
if(query[i].length > 1){
alphabetisedWord = alphabetisedWord.split('');
console.log('alpha : ', alphabetisedWord)
alphabetisedWord = alphabetisedWord.sort();
alphabetisedWord = alphabetisedWord.join('');
}
var regex = new RegExp("/" + alphabetisedWord + "/", "g");
console.log(stringAnagram(dictionary, query))
anagramsCount[i] = sortedDictionary.toString().match(regex).length
sortedQuery[i] = alphabetisedWord;
}
return anagramsCount;
}
Can anyone tell what's causing this? I have tried logging all the indexes and words but I did a similar question earlier with a similar method of answering - only this time, the endless loop has appeared and I have never seen this before.
If a simple problem seems impossible, you're doing it a wrong way... eek talking to myself too
const dictionary = ['hack', 'a' , 'rank' , 'khac','ackh']
const query = ['a','nark','bs','hack','stair']
console.log(stringAnagram(dictionary, query))
function stringAnagram(dd,qq){
var j=(x)=>{return JSON.parse(JSON.stringify(x))} //function to ensure an object isn't passed as pointer JUST IN CASE and to that dude critisizing this part, stringifying an already correctly evaluated obj works(therefore parsing that would be parsing a correctly stringified obj)
var d=j(dd); var q=j(qq)
//make words in both query and dictionary now have their words in only 1 format(so that indexOf would work like a charm)
d=d.map(a=>{return a.split``.sort().join``})
q=q.map(a=>{return a.split``.sort().join``})
//now onto indexOf logic(returns the FIRST find of what ur looking for in an array)
var arr=[]
q.forEach(a=>{
var i=0
while(d.indexOf(a)!=-1){
var y=d.indexOf(a)
i++;d.splice(y,1)
}
arr.push(i)
})
return(arr)
}

conditional splitting of string and word by matching characters in js

I have very long string that contains html as a string , numbers , my special bindings and numbers I want to split my bindings and sentences with spaces separately but my program is separately my bindings and words .
my js code:-
var x = 'hey this is {{name}} and I love to {{write}} and to learn as
much as I can. Now I am trying to separate sentences and my bindings'
var c = x.match(/\s*\S*\s*/g) // this splits words from string including
space
var mt = x.match(/{(.*)}/g); // trying to take out bindings but this don't
work
mt.forEach(function(a){ // taking each bindings separately
var z = x.match(a)
})
console.log(mt)
Somthing like this .. but I know this is totally wrong please help me
I don't have any idea :-
output that I am expecting:-
(5) ["hey this is", "i", "{{name}}", " and I love to ", "{{write}}", " and to learn as ↵ much as I can. Now I am trying to separate sentences and my bindings"]
How can i do this?
Please don't use jquery
Try this:
I've commented my code hoping it would make it easier to read. But do note that this code is far from perfect although it solves your problem.
var rawString = 'hey this is {{name}} and I love to {{write}} and to learn as much as I can. Now I am trying to separate sentences and my bindings';
var arrayRawString = rawString.match(/\s*\S*\s*/g); // this splits words from string including space
var arrayPlaceholder = rawString.match(/{(.\S*)}+/g); // trying to take out bindings but this don't work
// to store the final output
var separedArray = [];
// keeping track of the index to stich the array up
var posStart = 0;
var posEnd = 0;
arrayPlaceholder.forEach(function(arg){ // taking each bindings separately
// length of the array that holds placeholder (bindings)
var arsLength = arrayRawString.length;
for(var i = 0; i < arsLength; ++i) {
// if the provided text matches the original array's element
if(arrayRawString[i].match(arg)){
// to store the index
posEnd = arrayRawString.indexOf(arrayRawString[i]);
// join the pieces together upto the index defined
var res = arrayRawString.slice(posStart, posEnd).join('');
// to indicate whether the stored string is the placeholder
var flag = true;
// store the string obtained
separedArray.push(res.replace(arrayPlaceholder[(arrayPlaceholder.indexOf(arg) - 1) < 0 ? 0 : arrayPlaceholder.indexOf(arg) - 1 ], ''));
// check if the string still has placeholder (bindings)
// to remove it
for(var j = 0; j < arg.length; ++j) {
if(res[j] !== arg[j]) {
flag = !flag;
}
}
if ( flag ) {
separedArray.push(arg);
}
// last end position is the start position for next round
posStart = posEnd;
// because the loop runs only arrayPlaceholder.length times
// it solves the problem of last part not getting pushed to the final array
if( arrayPlaceholder[arrayPlaceholder.length-1] === arg ) {
res = arrayRawString.slice(posStart, arrayRawString.length).join('');
separedArray.push(res.replace(arg, ''));
}
}
}
});
console.log(separedArray);

JavaScript Search and Loop - doesn't return correct values

Please, can you check my code where is the error? It should loop trough 1 array to choose each string and then loop through second array and check, if the value from second string contains value of first string.
for (var i = 0; i < oldLines.length; i++){
var subStringEach = oldLines[i];
var subStringEachNoDash = subStringEach.replace(/[^a-z0-9]/g,'');
// read New URLs and line by line save them as an object
var newLines = $('#newUrl').val().split(/\n/);
var newUrlResult = [];
for (var j = 0; j < newLines.length; j++){
var newUrlString = newLines[j];
var newUrlStringNoDash = newUrlString.replace(/[^a-z0-9]/g,'');
var isThere = newUrlStringNoDash.search(subStringEachNoDash);
if (isThere !== -1 ) {
newUrlResult[i] = newLines[j];
}
else {
newUrlResult[i] = "";
}
}
stockData.push({OldURL:oldLines[i],SearchSubstring:subStringEach,NewURL:newUrlResult[i]});
}
Now it finds only part of the results.. I place to first array:
anica-apartment
casa-calamari-real
ostrovni-apartman
and to the second array:
http://tempweb3.datastack.cz/be-property/anica-apartment/
http://tempweb3.datastack.cz/be-property/ostrovni-apartman/
http://tempweb3.datastack.cz/be-property/st-michael-apartment/
http://tempweb3.datastack.cz/be-property/casa-calamari-real/
and it will only find and return casa-calamari-real, http://tempweb3.datastack.cz/be-property/casa-calamari-real/ and the others returns empty..
Any ideas please?
Here is the full code on Codepen: https://codepen.io/vlastapolach/pen/VWRRXX
Once you find a match you should exit the inner loop, otherwise the next iteration of that loop will clear again what you had matched.
Secondly, you should use push instead of accessing an index, as you don't know how many results you will have. And as a consequence you will need to relate the find string with it (because i will not be necessary the same in both arrays)
So replace:
if (isThere !== -1 ) {
newUrlResult[i] = newLines[j];
}
else {
newUrlResult[i] = "";
}
with this:
if (isThere !== -1 ) {
newUrlResult.push({
searchSubstring: subStringEach,
newURL: newUrlString
});
break; // exit loop
}
At the end, just output newUrlResult.
NB: If you want to leave the possibility that a search string matches with more than one URL, then you don't need the break. The push will then still prevent you from overwriting a previous result.
I see that you solved already) But maybe you will like this code too)
newUrlResult variable could be a string I guess, because loop breaks when one value is found. If no values where found there will be just empty string. And I'm not sure you need to call newLines = $('#newUrl').val().split(/\n/) on every iteration.
var stockData = [];
oldLines.map(function(oldLine){
var cleanOldLine = oldLine.replace(/[^a-z0-9]/g,''),
newLines = $('#newUrl').val().split(/\n/),
newUrlResult = '';
for (var j = 0; j < newLines.length; j++){
var newLine = newLines[j],
cleanNewLine = newLine.replace(/[^a-z0-9]/g,''),
ifExists = cleanNewLine.search(cleanOldLine);
if (ifExists !== -1) {
newUrlResult = newLine;
break;
}
}
stockData.push({OldURL:oldLine, SearchSubstring:cleanOldLine, NewURL:newUrlResult});
});

How Do I Parse a Pipe-Delimited String into Key-Value Pairs in Javascript

I want to parse the following sort of string into key-value pairs in a Javascript object:
var stringVar = 'PLNC||0|EOR|<br>SUBD|Pines|1|EOR|<br>CITY|Fort Myers|1|EOR|<br>';
Each word of 4 capital letters (PLNC, SUBD, and CITY) is to be a key, while the word(s) in the immediately following pipe are to be the value (the first one, for PLNC, would be undefined, the one for SUBD would be 'Pines', the one for CITY would be 'Fort Myers').
Note that '|EOR|' immediately precedes every key-value pair.
What is the best way of doing this?
I just realised it's technically a csv format with interesting line endings. There are limitations to this in that your variable values cannot contain any | or < br> since they are the tokens which define the structure of the string. You could of course escape them.
var stringVar = 'PLNC||0|EOR|<br>SUBD|Pines|1|EOR|<br>CITY|Fort Myers|1|EOR|<br>';
function decodeString(str, variable_sep, line_endings)
{
var result = [];
var lines = str.split(line_endings);
for (var i=0; i<lines.length; i++) {
var line = lines[i];
var variables = line.split(variable_sep);
if (variables.length > 1) {
result[variables[0]] = variables[1];
}
}
return result;
}
var result = decodeString(stringVar, "|", "<br>");
console.log(result);
If you have underscore (and if you don't, then just try this out by opening up your console on their webpage, because they've got underscore included :)
then play around with it a bit. Here's a start for your journey:
_.compact(stringVar.split(/<br>|EOR|\|/))
Try
function parse(str) {
var str = str.replace(/<br>/gi);
console.log(str);
var arr = str.split('|');
var obj = {};
for (var i=0; i<arr.length; i=i+4) {
var key = arr[i] || '';
var val_1 = arr[i+1] || '';
var val_2 = arr[i+2] || '';
if(key) {
obj[key] = val_1 + ':' + val_2; //or similar
}
}
return obj;
}
DEMO
This will work on the particular data string in the question.
It will also work on other data string of the same general format, but relies on :
<br> being discardable before parsing
every record being a group of 4 string elements delineated by | (pipe)
first element of each record is the key
second and third elements combine to form the value
fourth element is discardable.

Javascript regular expressions for Query Builder

This may have been asked in the past but I couldnt find a suitable answer. What I am looking for is a method to extract parameters from an sql query such as below. The queries will always be an EXEC statement followed by the query name, and possible parameters.
Here is an example of what I may recieve
EXEC [dbo].[myProcedure] #Param1
This could also be as follows
EXEC [dbo].[myProcedure] #Param1, #Param2, #Param3
Those are the only types of queries that the input will take. As for why I am doing this, well thats another question all together, and I am pretty set on going down this route.
What I am looking for is to be able to take the above strings and produce an array of values such as
['#Param1','#Param2','#Param3',....]
I originally tried to just parese using a simple while statement but I seem to have huge issues there.
I hope this question makes sense,
Cheers,
Nico
[Edit]
Sorted this by using the following statement
function eParams(e) {
var i = e.indexOf('#');
if (i <= 0)
return;
e = e.substring(i);
var p = e.split(',');
var eList = [];
var s = '';
for (var i = 0, j = p.length - 1; i <= j; i++) {
var sP = p[i].trim();
if (sP.indexOf('#') < 0)
continue;
eList.push(sP);
}
}
var str = 'EXEC [dbo].[myProcedure] #Param1, #Param2, #Param3';
(str).match(/(#[^\s,]+)/g);
will return an array.
var s = "EXEC [dbo].[myProcedure] #Param1, #Param2, #Param3";
var i = s.indexOf('#');
var a = s.substr(i).split(/\s*,\s*/);
(error checking omitted)

Categories

Resources