Matching two strings stored in different variables in nodejs - javascript

I am new to node.js. I was practising a program to find a pattern in a string and extracting that part of line from the file.
File as:
Something written in a file saved as filename.ext.
At a line, it contains a link.
import "https:\//www.hostname.com/$path"
I want to extract the link from any line in a file.
I was trying to match the pattern to get index no of 'h' in 'http' and extracting it further. Stuck at nm() as it isn't working on variable as parameter.
var url=require('url')
var fs = require('fs');
var find = require('find');
var findInFiles = require('find-in-files');
var LineReader = require('linereader');
var nm = require('nanomatch');
var sol=require('./../bin/sol-merger')
var dir = './merged/';
var pth=process.cwd()+'/'+dir+'newfile.sol'
var flag=0
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
fs.createReadStream(sol.abs_path).pipe(fs.createWriteStream(dir+'/newfile.sol'));
findInFiles.find({'term': "http", 'flags': 'ig'}, 'merged/', '.sol$').then(function(results) {
//console.log("here...")
for (var result in results) {
var res = results[result];
console.log('found "' + res.matches[0] + '" ' + res.count+ ' times in "' + result + '"')
console.log(sol.fl+" "+result)
}
var lr=new LineReader(pth)
lr.on('error', function (err) {
console.log(err);
console.log("error")
lr.close();
});
lr.on('line', function (lineno, line) {
console.log(lineno + " " + line);
if(nm.contains(`$line`,'*"http**"*')){
console.log("found")
}
});
})

Change
findInFiles.find({'term': "http", 'flags': 'ig'}, 'merged/', '.sol$')
to
var regex = 'http.*?(?=\")'
findInFiles.find({term: regex, flags: 'g'}, 'merged/', '.sol$')
The regex matches http/https link till " is found at end of link, but doesn't capture " in group. (?=\") is positive lookahead match.
See regular expression's explanation and working example here - https://regex101.com/r/4RAr0Z/1

I would use regex, e.g.:
//read in eg with fs module
var _test = 'import "https://www.github.com/xyz/abc.txt" \n import "https://www.github.com/xyz/xab.txt"';
var _reg = /["](.*?)["]/gm;
var _my_matches = _test.match(_reg);
console.log(_my_matches); //array with all matches
Please note, this is a minimal example. I recommend to test out your required regex setup at https://regex101.com/ (or something similar)

Related

Join three variables and later extract with regex

I am joining together 3 variables into a filename seperated by a -- for use in another Cloud function. I do this with the following code below:
const newFileName = size + "--" + bytes + "--" + name + ".txt";
How can I seperate these later with Regex?
size (extract before first --)
bytes (extract after first --)
name (extract after second --)
If you always use the same extension .txt you might remove that part from the string and then split on --
let str = "aaa--bbb--ccc.txt";
[size, bytes, name] = str.substring(0, str.length - 4).split("--");
console.log(size);
console.log(bytes);
console.log(name);
Another option could be to split on either -- or on a pattern that would match the last dot followed by matching not a dot until the end of the string.
let str = "aaa--bbb--ccc.txt";
[size, bytes, name] = str.split(/--|\.[^.]+$/);
console.log(size);
console.log(bytes);
console.log(name);
If you use this regex, it will pull the three parts into 3 different capture groups named "size", "bytes", and "name":
^(?<size>.*?)\-\-(?<bytes>.*?)\-\-(?<name>.*?[.txt])$
In javascript, you can use this code to pull the groups out afterwards:
var reg = /^(?<size>.*?)\-\-(?<bytes>.*?)\-\-(?<name>.*?[.txt])$/
var matches = "123--456--test.txt".match(reg);
var size = matches["groups"]["size"]
var bytes = matches["groups"]["bytes"]
var name = matches["groups"]["name"]
Where the "123--456--test.txt" string is instead the string you want to pull the data out of.
EDIT:
Like StackSlave pointed out, named capture groups like above are not always supported. If you need to support a browser or language that can't deal with named groups, you can instead do this:
var reg = /^(.*?)\-\-(.*?)\-\-(.*?)$/
var matches = "123--456--test.txt".match(reg);
var size = matches[1]
var bytes = matches[2]
var name = matches[3]
EDIT EDIT:
To get the file name without extension, use this regex instead:
var reg = /(.*?)\-\-(.*?)\-\-(.*?)\./
var matches = "123--456--test.txt".match(reg);
var size = matches[1]
var bytes = matches[2]
var name = matches[3]
Here's a numeric example:
var str = 'size--bytes--name.ext', m = str.match(/^(.+)--(.+)--(.+)(?:\..+)$/);
console.log(m); console.log('size:'+m[1]); console.log('bytes:'+m[2]); console.log('name:'+m[3]);

Update uri hash javascript

I find it hard to believe this hasn't been asked but I can find no references anywhere. I need to add a URI hash fragment and update the value if it already is in the hash. I can currently get it to add the hash but my regex doesn't appear to catch if it exists so it adds another instead of updating.
setQueryString : function() {
var value = currentPage;
var uri = window.location.hash;
var key = "page";
var re = new RegExp("([#&])" + key + "=.*#(&|$)", "i");
var separator = uri.indexOf('#') !== -1 ? "&" : "#";
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
},
Also if this can be made any cleaner while preserving other url values/hashes that would be great.
example input as requested
Starting uri value:
www.example.com#page=1 (or no #page at all)
then on click of "next page" setQueryString gets called so the values would equal:
var value = 2;
var uri = '#page1'
var key = 'page'
So the hopeful output would be '#page2'.
As to your regex question, testing if the pattern #page=(number) or &page=(number) is present combined with capturing the number, can be done with the regex /[#&]page\=(\d*)/ and the .match(regex) method. Note that = needs escaping in regexes.
If the pattern exists in the string, result will contain an array with the integer (as a string) at result[1]. If the pattern does not exist, result will be null.
//match #page=(integer) or &page=(integer)
var test = "#foo=bar&page=1";
var regex = /[#&]page\=(\d*)/;
var result = test.match(regex);
console.log(result);
If you want to dynamically set the key= to something other than "page", you could build the regex dynamically, like the following (note that backslashes needs escaping in strings, making the code a bit more convoluted):
//dynamically created regex
var test = "#foo=bar&page=1";
var key = "page"
var regex = new RegExp("[#&]" + key + "\\=(\\d*)");
var result = test.match(regex);
console.log(result);

Javascript string concatenate in the wrong order

I'm trying to generate a character from these three arrays. My code is as follows, but I can't figure out why the string doesn't concatenate as I've written. Some of it is missing, and the ending . even comes at the start at some times. Occasionally it works, but a lot of the times the output fails.
//Arrays
var character = ["man", "woman"];
var feature = ["one leg", "a drinking problem"];
var purpose = ["stay home", "leave home"];
function createSentence(){
var char = getRandomItem(character);
var feat = getRandomItem(feature);
var purp = getRandomItem(purpose);
var sentence = "A " + char + " with " + feat + ", that wants to " + purp + ".";
return sentence;
}
// Gets a random item from an input array
function getRandomItem(array){
var index = Math.floor(Math.random()*array.length);
return array[index];
}
Here's what I get in my console. . at the start and missing the "character"-part.
.with a drinking problem, that wants to leave home
EDIT: Sorry for not including this, as I guess this is very relevant here as well. I assumed the arrays were fine, but I might be missing something. When I print out the arrays after parsing them they look exactly like what I posted above.
// How i set up my arrays
var character = parseTextFile("character.txt");
var feature = parseTextFile("feature.txt");
var purpose = parseTextFile("purpose .txt");
// Parsing a file
function parseTextFile(filename){
var array = fs.readFileSync(filename).toString().split("\n");
return array;
}
/* --- character.txt ---*/
man
woman
Thank you.
// How i set up my arrays
var character = parseTextFile("character.txt");
var feature = parseTextFile("feature.txt");
var purpose = parseTextFile("purpose .txt");
// Parsing a file
function parseTextFile(filename){
//fs.read requires absolute path
var array = fs.readFileSync(__dirname + '/' + filename, 'utf8') // <-- specify format
.split('\n')
.filter(function(text) { return !!text; }); // <-- return only not-empty string
return array;
}

Regex mapping in Firefox context menu contentScript

I am developing context menu add-on for Firefox. I am trying to get the selectedText and validate if it is a number. If it is a number i am using that number value to process further.
But, i got stuck at a point where i am trying to replace [(,)] using regex in javascript replace method.
Following is the code which fails to map any number starting/ending with ( or ):
var menuItemLRG = contextMenu.Item({
label: "LRG",
data: "http://myurl/&val=:",
contentScript: 'self.on("click", function (node, data) {' +
' var selectedText = window.getSelection().toString();' +
' var formattedText1 = selectedText.trim();' +
' var formattedText2 = formattedText1.replace(/^[,\[\]()]*/g,"");' +
' var formattedText3 = formattedText2.replace(/[,\[\]()]*$/g,"");' +
' console.log(formattedText3); '+
' var regExp = new RegExp(/^[0-9]+$/);' +
' if (regExp.test(formattedText3) == true) {' +
' console.log("URL to follow :"+data+formattedText3);' +
' window.open(data+formattedText3);' +
' } '+
'});'
});
Above code fails to replace ( or ) in sample inputs: (5663812, 11620033).
But, a vanilla test like the following succeeds:
<script>
var str = "(2342423,])";
var tmpVal1 = str.replace(/^[,\[\]()]*/g,"");
var tmpVal2 = tmpVal1.replace(/[,\[\]()]*$/g,"");
var regExp = new RegExp(/^[0-9]+$/);
if (regExp.test(tmpVal2) == true) {
alert(tmpVal2);
}
</script>
After many trial and error found the issue. When we try to escape a character inside a single quotes we need to add one more escape for the escape character to get recognized, otherwise the single escape \] will be considered as ] which leads to abrupt ending of of the regex pattern.
In this case:
' var formattedText2 = formattedText1.replace(/^[,\[\]()]*/g,"");'
is decoded as :
var formattedText2 = formattedText1.replace(/^[,[]()]*/g,"");
instead of as:
var formattedText2 = formattedText1.replace(/^[,\[\]()]*/g,"");
So, by adding one more escape character for an escape character resolved the pattern correctly:
' var formattedText2 = formattedText1.replace(/^[,\\[\\]()]*/g,"");'
Sorry for wasting your time in analyzing the cause, if any.

Trimming a string from the end in Javascript

In Javascript, how can I trim a string by a number of characters from the end, append another string, and re-append the initially cut-off string again?
In particular, I have filename.png and want to turn it into filename-thumbnail.png.
I am looking for something along the lines of:
var sImage = "filename.png";
var sAppend = "-thumbnail";
var sThumbnail = magicHere(sImage, sAppend);
You can use .slice, which accepts negative indexes:
function insert(str, sub, pos) {
return str.slice(0, pos) + sub + str.slice(pos);
// "filename" + "-thumbnail" + ".png"
}
Usage:
insert("filename.png", "-thumbnail", -4); // insert at 4th from end
Try using a regular expression (Good documentation can be found at https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions)
I haven't tested but try something like:
var re = /(.*)\.png$/;
var str = "filename.png";
var newstr = str.replace(re, "$1-thumbnail.png");
console.log(newstr);
I would use a regular expression to find the various parts of the filename and then rearrange and add strings as needed from there.
Something like this:
var file='filename.png';
var re1='((?:[a-z][a-z0-9_]*))';
var re2='.*?';
var re3='((?:[a-z][a-z0-9_]*))';
var p = new RegExp(re1+re2+re3,["i"]);
var m = p.exec(file);
if (m != null) {
var fileName=m[1];
var fileExtension=m[2];
}
That would give you your file's name in fileName and file's extension in fileExtension. From there you could append or prepend anything you want.
var newFile = fileName + '-thumbnail' + '.' + fileExtension;
Perhaps simpler than regular expressions, you could use lastindexof (see http://www.w3schools.com/jsref/jsref_lastindexof.asp) to find the file extension (look for the period - this allows for longer file extensions like .html), then use slice as suggested by pimvdb.
You could use a regular expression and do something like this:
var sImage = "filename.png";
var sAppend = "-thumbnail$1";
var rExtension = /(\.[\w\d]+)$/;
var sThumbnail = sImage.replace(rExtension, sAppend);
rExtension is a regular expression which looks for the extension, capturing it into $1. You'll see that $1 appears inside of sAppend, which means "put the extension here".
EDIT: This solution will work with any file extension of any length. See it in action here: http://jsfiddle.net/h4Qsv/

Categories