Question:
Is it possible to keep the selected delimiter using javascript [.split], without involving regex? In below example I am sending in the commands using node.js.
// A css text string.
var text_string = "div-1{color:red;}div-2{color:blue;}";
// Split by [}], removes the delimiter:
var partsOfStr = text_string.split('}');
// Printouts
console.log("Original: " + text_string); // Original.
console.log(partsOfStr); // Split into array.
console.log(partsOfStr[0]); // First split.
console.log(partsOfStr[1]); // Second split.
The output:
Original: div-1{color:red;}div-2{color:blue;}
[ 'div-1{color:red;', 'div-2{color:blue;', '' ]
div-1{color:red;
div-2{color:blue;
Wanted behaviour:
I need the output to include the delimitor [ } ]. The result lines should look line this:
div-1{color:red};
div-2{color:blue};
I did find below question but it does not use javascript split, it uses regex:
Javascript split include delimiters
Here's a way using replace - although technically there is a regex involved. Techical in an almost pedantic way since it matches the actual strings, only between slashes rather than quotes.
var text_string = "div-1{color:red;}div-2{color:blue;}";
var partsOfString = text_string.replace(/;}/g, "};\n")
console.log(partsOfString);
Related
I currently have the following string :
AAAAA/BBBBB/1565079415419-1564416946615-file-test.dsv
But I would like to split it to only get the following result (removing all tree directories + removing timestamp before the file):
1564416946615-file-test.dsv
I currently have the following code, but it's not working when the filename itselfs contains a '-' like in the example.
getFilename(str){
return(str.split('\\').pop().split('/').pop().split('-')[1]);
}
I don't want to use a loop for performances considerations (I may have lots of files to work with...) So it there an other solution (maybe regex ?)
We can try doing a regex replacement with the following pattern:
.*\/\d+-\b
Replacing the match with empty string should leave you with the result you want.
var filename = "AAAAA/BBBBB/1565079415419-1564416946615-file-test.dsv";
var output = filename.replace(/.*\/\d+-\b/, "");
console.log(output);
The pattern works by using .*/ to first consume everything up, and including, the final path separator. Then, \d+- consumes the timestamp as well as the dash that follows, leaving only the portion you want.
You may use this regex and get captured group #1:
/[^\/-]+-(.+)$/
RegEx Demo
RegEx Details:
[^\/-]+: Match any character that is not / and not -
-: Match literal -
(.+): Match 1+ of any characters
$: End
Code:
var filename = "AAAAA/BBBBB/1565079415419-1564416946615-file-test.dsv";
var m = filename.match(/[^\/-]+-(.+)$/);
console.log(m[1]);
//=> 1564416946615-file-test.dsv
In python there exists ast.literal_eval(x) where if x is "['a','b','c']" then it will return the list ['a','b','c']. Does something similar exist in Javascript / jQuery where I can take the array that is stored in the table cell as [x,y,z] and turn that into a literal JavaScript array?
I'd prefer to avoid any complex solutions that might be error prone since it's possible that involve splitting on the comma or escaping characters.
Edit: I should have given some better examples:
['la maison', "l'animal"] is an example of one that hits an error because doing a replace of a single or double quote can cause an issue since there's no guarantee on which one it'll be.
One could leverage String.prototype.replace() and JSON.parse().
See below for a rough example.
// String.prototype.replace() + JSON.parse() Strategy.
const input = "['a','b','c']" // Input.
const array = JSON.parse(input.replace(/'/g, '"')) // Array.
console.log(array) // Proof.
Although, given your update/more complex use case, eval() might be more appropriate.
// eval() Strategy.
const input = `['la maison', "l'animal"]` // Input.
const dangerousarray = eval(input) // Array.
const safearray = eval(`new Array(${input.replace(/^\[|\]$/g, '')})`)
console.log(dangerousarray) // Proof.
console.log(safearray) // Proof.
However, the MDN docs discourage use of eval() due to security/speed flaws.
As a result, one may opt for an approach similar to the following:
// Heavy Replacement Strategy.
const input = `['la maison', 'l\'animal']` // Input.
const array = input
.replace(/^\[|\]$/g, '') // Remove leading and ending square brackets ([]).
.split(',') // Split by comma.
.map((phrase) => // Iterate over each phrase.
phrase.trim() // Remove leading and ending whitespace.
.replace(/"/g, '') // Remove all double quotes (").
.replace(/^\'|\'$/g, '') // Remove leading and ending single quotes (').
)
console.log(array) // Proof.
In JavaScript you can use eval() Function like the sample bellows :
// define the string to evaluate
var str_to_evaluate = 'new Array("Saab", "Volvo", "BMW")';
// retreive the result in a array
var cars = eval(str_to_evaluate);
// print the array
console.log(cars);
So to start off, a bit of context. I am pulling data from the following url: "https://webster.cs.washington.edu/pokedex/pokedex.php?pokedex=all" using a GET method. The data returned is a series of Pokemon names and image names in the following format.
Name1:name1.png
Name2:name2.png
...
The list is 151 items long. When I call the typeOf() method "String" is returned, so I am fairly certain it is a String I am dealing with here. What I would like to do is split the String on the delimiters of "\n" and ":".
What I would like:
Name1,name1.png,Name2,name2.png...
After some experimentation with Regex, I found that the Regex to do this was "\n|:". Using this I wrote the following line to split the String apart. I tested this Regex on https://regex101.com and it seems to work properly there.
var splitData = data.split("\n|:");
("data" is the String I receive from the url.)
But instead of splitting the String and placing the substrings into an array it doesn't do anything. (At least as far as I can see.) As such my next idea was to try replacing the characters that were giving me trouble with another character and then splitting on that new character.
data = data.replace("\n", " ");
data = data.replace("/:/g", " ");
var splitData = data.split(" ");
The first line that replaces new line characters does work, but the second line to replace the ":" does not seem to do anything. So I end up with an array that is filled with Strings that look like this.
Name1:name1.png
I can split these strings by calling their index and then splitting the substring stored within, which only confuses me more.
data = data.replace("\n", " ");
var splitData = data.split(" ");
alert(splitData[0].split(":")[1]);
The above code returns "name1.png".
Am I missing something regarding the split() method? Is my Regex wrong? Is there a better way to achieve what I am attempting to do?
Right now you are splitting on the string literal "\n|:" but to do a regex you want data.split(/[:\n]/)
The MDN page shows two ways to build a Regex:
var regex1 = /\w+/;
var regex2 = new RegExp('\\w+');
The following test script was able to work for me. I decided to use the regex in the split instead of trying to replace tokens in the string. It seemed to do the trick for me.
let testResponse = `Abra:abra.png
Aerodactyl:aerodactyl.png`;
let dataArray = testResponse.split(/\n|:/g);
let commaSeperated = dataArray.join(',');
console.log(commaSeperated);
So you can simply use regex by excluding the quotes all together.
You can look at the documentation here for regular expressions. They give the following examples:
var re = /ab+c/;
var re = new RegExp('ab+c');
See below for your expected output:
var data = `Name1:name1.png
Name2:name2.png`;
var splitData = data.split(/[\n:]/);
console.log(splitData);
//Join them by a comma to get all results
console.log(splitData.join(','));
//For some nice key value pairs, you can reduce the array into an object:
var kvps = data.split("\n").reduce((res, line) => {
var split = line.split(':');
return {
...res,
[split[0]]: split[1]
};
}, {});
console.log(kvps);
I tried and this works good.
str.split(/[:\n]/)
Here is a plunker.
plunker
Let's say I have a string: "We.need..to...split.asap". What I would like to do is to split the string by the delimiter ., but I only wish to split by the first . and include any recurring .s in the succeeding token.
Expected output:
["We", "need", ".to", "..split", "asap"]
In other languages, I know that this is possible with a look-behind /(?<!\.)\./ but Javascript unfortunately does not support such a feature.
I am curious to see your answers to this question. Perhaps there is a clever use of look-aheads that presently evades me?
I was considering reversing the string, then re-reversing the tokens, but that seems like too much work for what I am after... plus controversy: How do you reverse a string in place in JavaScript?
Thanks for the help!
Here's a variation of the answer by guest271314 that handles more than two consecutive delimiters:
var text = "We.need.to...split.asap";
var re = /(\.*[^.]+)\./;
var items = text.split(re).filter(function(val) { return val.length > 0; });
It uses the detail that if the split expression includes a capture group, the captured items are included in the returned array. These capture groups are actually the only thing we are interested in; the tokens are all empty strings, which we filter out.
EDIT: Unfortunately there's perhaps one slight bug with this. If the text to be split starts with a delimiter, that will be included in the first token. If that's an issue, it can be remedied with:
var re = /(?:^|(\.*[^.]+))\./;
var items = text.split(re).filter(function(val) { return !!val; });
(I think this regex is ugly and would welcome an improvement.)
You can do this without any lookaheads:
var subject = "We.need.to....split.asap";
var regex = /\.?(\.*[^.]+)/g;
var matches, output = [];
while(matches = regex.exec(subject)) {
output.push(matches[1]);
}
document.write(JSON.stringify(output));
It seemed like it'd work in one line, as it did on https://regex101.com/r/cO1dP3/1, but had to be expanded in the code above because the /g option by default prevents capturing groups from returning with .match (i.e. the correct data was in the capturing groups, but we couldn't immediately access them without doing the above).
See: JavaScript Regex Global Match Groups
An alternative solution with the original one liner (plus one line) is:
document.write(JSON.stringify(
"We.need.to....split.asap".match(/\.?(\.*[^.]+)/g)
.map(function(s) { return s.replace(/^\./, ''); })
));
Take your pick!
Note: This answer can't handle more than 2 consecutive delimiters, since it was written according to the example in the revision 1 of the question, which was not very clear about such cases.
var text = "We.need.to..split.asap";
// split "." if followed by "."
var res = text.split(/\.(?=\.)/).map(function(val, key) {
// if `val[0]` does not begin with "." split "."
// else split "." if not followed by "."
return val[0] !== "." ? val.split(/\./) : val.split(/\.(?!.*\.)/)
});
// concat arrays `res[0]` , `res[1]`
res = res[0].concat(res[1]);
document.write(JSON.stringify(res));
I'm having difficulties with constructing some regular expressions using Javascript.
What I need:
I have a string like: Woman|{Man|Boy} or {Girl|Woman}|Man or Woman|Man etc.
I need to split this string by '|' separator, but I don't want it to be split inside curly brackets.
Examples of strings and desired results:
// Expample 1
string: 'Woman|{Man|Boy}'
result: [0] = 'Woman', [1] = '{Man|Boy}'
// Example 2
string '{Woman|Girl}|{Man|Boy}'
result: [0] = '{Woman|Girl}', [1] = '{Man|Boy}'
I can't change "|" symbol to another inside the brackets because the given strings are the result of a recursive function. For example, the original string could be
'Nature|Computers|{{Girls|Women}|{Boys|Men}}'
try this:
var reg=/\|(?![^{}]+})/g;
Example results:
var a = 'Woman|{Man|Boy}';
var b = '{Woman|Girl}|{Man|Boy}';
a.split(reg)
["Woman", "{Man|Boy}"]
b.split(reg)
["{Woman|Girl}", "{Man|Boy}"]
for your another question:
"Now I have another, but a bit similar problem. I need to parse all containers from the string. Syntax of the each container is {sometrash}. The problem is that container can contain another containers, but I need to parse only "the most relative" container. mystring.match(/\{+.+?\}+/gi); which I use doesn't work correctly. Could you correct this regex, please? "
you can use this regex:
var reg=/\{[^{}]+\}/g;
Example results:
var a = 'Nature|Computers|{{Girls|Women}|{Boys|Men}}';
a.match(reg)
["{Girls|Women}", "{Boys|Men}"]
You can use
.match(/[^|]+|\{[^}]*\}/g)
to match those. However, if you have a nesting of arbitrary depth then you'll need to use a parser, [javascript] regex won't be capable of doing that.
Test this:
([a-zA-Z0-9]*\|[a-zA-Z0-9]*)|{[a-zA-Z0-9]*\|[a-zA-Z0-9]*}