I'd like to split a string if:
It doesn't starts with a quatre or a soixante AND
It doesn't ends with a dix or a vingt
For example:
'deux-cent-quatre-vingt-trois'.split(/**/);
> ['deux', 'cent', 'quatre-vingt', 'trois' ]
I've had a few tries and failures, for example:
'deux-cent-quatre-vingt-dix-trois'
.split(/^(?![quatre|soixante]-[dix|vingt])(\w*)-(\w*)/);
> [ '', 'deux', 'cent', '-quatre-vingt-trois' ]
or:
'deux-cent-quatre-vingt-dix-trois'.split(/(?!quatre|soixante)-(?!vingt|dix)/);
> [ 'deux' 'cent', 'quatre-vingt', 'trois' ]
which works, but this does not:
'cent-vingt'.split(/(?!quatre|soixante)-(?!vingt|dix)/);
> [ 'cent-vingt' ]
I know using a matcher or a find would be so easy, but it would be great to do it in a single split...
You can do it like this:
var text = "deux-cent-quatre-vingt-trois";
console.log(text.split(/(?:^|-)(quatre-vingt(?:-dix|s$)?|soixante-dix|[^-]+)/));
The idea is to add a capturing group whose content is added to the split list.
The capturing group contains at first particular cases and after the most general, described with [^-]+ (all that is not a -)
Notice: since quatre-vingt is written with a s when it is not followed by a number, i added s$ as a possibility.
Related
I am trying to split a string into an array of text contents which each are present within the [# and ] delimiters. Just characters in between [#and ] are allowed to match. Being provided with a string like ...
const stringA = '[#Mary James], [#Jennifer John] and [#Johnny Lever[#Patricia Robert] are present in the meeting and [#Jerry[#Jeffery Roger] is absent.'
... the following result is expected ...
[
'Mary James',
'Jennifer John',
'Patricia Robert',
'Jeffery Roger'
]
Any logic which leads to the expected outcome can be used.
A self search for a solution brought up the following applied regex ...
stringA.match(/(?<=\[#)[^\]]*(?=\])/g);
But the result doesn't fulfill the requirements because the array features the following items ...
[
'Mary James',
'Jennifer John',
'Johnny Lever[#Patricia Robert',
'Jerry[#Jeffery Roger'
]
The OP's regex does not feature the opening bracket within the negated character class, thus changing the OP's /(?<=\[#)[^\]]*(?=\])/g to (?<=\[#)[^\[\]]*(?=\]) already solves the OP's problem for most environments not including safari browsers due to the lookbehind which is not supported.
Solution based on a regex ... /\[#(?<content>[^\[\]]+)\]/g ... with a named capture group ...
const sampleText = '[#Mary James], [#Jennifer John] and [#Johnny Lever[#Patricia Robert] are present in the meeting and [#Jerry[#Jeffery Roger] is absent.'
// see ... [https://regex101.com/r/v234aT/1]
const regXCapture = /\[#(?<content>[^\[\]]+)\]/g;
console.log(
Array.from(
sampleText.matchAll(regXCapture)
).map(
({ groups: { content } }) => content
)
);
Close, just missing the exclusion of [:
stringA.match(/(?<=\[#)[^\[\]]*(?=\])/g);
// ^^ exclude '[' as well as ']'
In Javascript using string.match():
I have a string like: foo_2:asc,foo2:desc,foo3,foo4:wrong
the matches should look like ["foo_2:asc", "foo2:desc", "foo3"]
but instead the best I can get it to so far is a match returning ["foo_2:asc", "foo2:desc", "foo3", "wrong"]
the regex that I'm using currently for the above wrong match is: /([a-z0-9_]+?[:asc|:desc]*?)(?=,|$)/gi
I also need a regex that will return the opposite, i.e. find a match for all patterns between the delimiter that doesn't match the pattern rules of thing_1:asc, thing_1:desc, or thing_1 i.e. this would be used to validate the string, while the other would be used to gather the values (i.e. instead of splitting the string manually). So the result of the original would be ["foo4:wrong"] as the part of that string that doesn't meet the pattern.
Assuming that the only valid forms are words followed by one of :asc, :desc or nothing, you can do what you want by splitting the string, first on , and then on : and checking whether there are two values as a result of the last split and the second is not one of asc or desc:
const str = 'foo_2:asc,foo2:desc,foo3,foo4:wrong';
const errs = str.split(',').filter(v => v.split(':').length == 2 && ['asc', 'desc'].indexOf(v.split(':')[1]) == -1);
console.log(errs);
If you must use regex, you can split on , and then filter based on the value not matching ^\w+(:(asc|desc))$:
const str = 'foo_2:asc,foo2:desc,foo3,foo4:wrong';
const errs = str.split(',').filter(v => !v.match(/^\w+(:(?:asc|desc))?$/));
console.log(errs);
If the format of the string is guaranteed to be \w+(:\w+)?(,\w+(:\w+)?)* you can simplify to this:
const str = 'foo_2:asc,foo2:desc,foo3,foo4:wrong';
const errs = str.match(/\w+:(?!(?:asc|desc)\b)\w+/g);
console.log(errs);
If you'd like regex for this purpose, you probably can just add start from coma or string start.
/(^|\,)([a-z0-9_]+?(:asc|:desc)*?)(?=,|$)/gi
also pay attention [:asc|:desc] changed to (:asc|:desc), to avoid false positive cases like:
foo5:aaa,foo6:d,foo7:,foo8|,et:c
it just matches by any char in square brackets.
Regarding opposite, try something like:
/(^|\,)(?!([a-z0-9_]+?(:asc|:desc)*?)(?=,|$))[^,$]+/gi
seems to do the job.
For the match I came up with
/(?<=(^|,))((\w+(?!:)|\w+(:asc|:desc)))(?=($|,))/g
Example: https://regex101.com/r/QLJeDV/3/
> "foo_2:asc,foo2:desc,foo3,foo4:wrong".match(/(?<=(^|,))((\w+(?!:)|\w+(:asc|:desc)))(?=($|,))/g)
[ 'foo_2:asc', 'foo2:desc', 'foo3' ]
Or even
/(?<=(^|,))\w+(:asc|:desc)?(?=($|,))/g
should work. Example: https://regex101.com/r/QLJeDV/6/
> "foo_2:asc,foo2:desc,foo3,foo4:wrong".match(/(?<=(^|,))\w+(:asc|:desc)?(?=($|,))/g)
[ 'foo_2:asc', 'foo2:desc', 'foo3' ]
They are using lookahead and lookbehind.
For the "opposite", I don't know how to match something and then "negate" a later pattern, but only know how to negate the result of whether it is a complete match, so I had to split it. The "opposite":
> "foo_2:asc,foo2:desc,foo3,foo4:wrong".split(",").filter(s => !/^((\w+(?!:)|\w+(:asc|:desc)))$/.test(s))
[ 'foo4:wrong' ]
and the "original":
> "foo_2:asc,foo2:desc,foo3,foo4:wrong".split(",").filter(s => /^((\w+(?!:)|\w+(:asc|:desc)))$/.test(s))
[ 'foo_2:asc', 'foo2:desc', 'foo3' ]
Or it can be simplified as:
> "foo_2:asc,foo2:desc,foo3,foo4:wrong".split(",").filter(s => !/^\w+(:asc|:desc)?$/.test(s))
[ 'foo4:wrong' ]
> "foo_2:asc,foo2:desc,foo3,foo4:wrong".split(",").filter(s => /^\w+(:asc|:desc)?$/.test(s))
[ 'foo_2:asc', 'foo2:desc', 'foo3' ]
I have a string which can be of variable length, for this question I will keep it simply and assume a small subset of items in the list.
The objective is to split the string to create multiple string values where the length is greater than 11, however I would need to preserve the comma values (e.g. I can't just split every 11 characters, I must split at the last comma before the 11th character
test1,test2,test3,test4,test5
For arguments sake, lets propose the max length of the string can be 10 characters, so in this example the above would be converted to three separate strings:
test1,test2
test3,test4
test5
To clarify there is a maximum allowed character limit of 11 characters per split value, but we want to use these as efficiently as possible.
You can use ( when you want to treat as 10 as min length and want to continue upto to the next upcoming , or end of string )
(.{10,}?)(?:,|$)
const input = 'test1,test2,test3,test4,test5';
console.log(
input.split(/(.{10,}?)(?:,|$)/g).filter(Boolean)
);
Update:- Since you want the value in between a range you can use this
(.{1,22})(?:,|$)
Demo
I am not sure if you are looking for something like this. But this code gives the output according to your example :
// Try edit msg
var msg = 'test1,test2,test3,test4,test5'
msgs = msg.split(",")
final = []
str = ""
msgs.map( m => {
str += str == "" ? m : "," + m
if (str.length > 10){
final.push(str)
str = ""
}
})
final.push(str)
console.log(final)
OUTPUT:
[
"test1,test2" ,
"test3,test4" ,
"test5"
]
Use a regular expression to match a non-comma, followed by up to 8 characters, followed by another non-comma, and lookahead for either a comma or the end of the string:
const input = 'test1,test2,test3,test4,test5';
console.log(
input.match(/[^,].{0,8}[^,](?=,|$)/g)
);
Because in the given input, test1,test2 (and any other combination of multiple items) will be length 11 or more, they won't be included.
If you want to allow length 11 as well, then change {0,8} to {0,9}:
const input = 'test1,test2,test3,test4,test5';
console.log(
input.match(/[^,].{0,9}[^,](?=,|$)/g)
);
If there might be items of length 1, make everything matched after the first non-comma optional in a non-capturing group:
const input = 'test1,test2,test3,test4,t';
console.log(
input.match(/[^,](?:.{0,9}[^,])?(?=,|$)/g)
);
I want to split '9088{2}12{1}729' into [ "9088", "{2}12", "{1}729" ]
or even more useful to me: [ "9088", "2-12", "1-729" ]
tried:
'9088{2}12{1}729'.split(/\{[0-9]+\}/); => ["9088", "12", "729"]
also tried:
'9088{2}12{1}729'.match(/\{[0-9]+\}/); => ["{2}"]
I know it probably involved some other regexp string to split including delimiters.
Tried it in php, I guess you can do it in one line also.
preg_split( '/{/', preg_replace( '/}/', '-', "9088{2}12{1}729" ) )
Array ( [0] => 9088 [1] => 2-12 [2] => 1-729 )
Just have to wrap the replace function with split to get the preference order correct.
I think I like js more :)
even more useful to me: [ "9088", "2-12", "1-729" ]
It can be done using simple tricks!
"9088{2}12{1}729".replace(/\}/g,'-').split(/\{/g)
// ["9088", "2-12", "1-729"]
You can use a simple zero-width positive lookahead with /(?={)/:
'9088{2}12{1}729'.split(/(?=\{)/); // => ["9088","{2}12","{1}729"]
The "zero-width" part means that the actual matched text is the empty string so the split throws away nothing, and the lookahead means it matches just before the contained pattern, so /(?=\{)/ matches the empty strings between characters where indicated by an arrow:
9 0 8 8 { 2 } 1 2 { 1 } 7 2 9
↑ ↑
You can then use Array.prototype.map to convert from {1}2 form to 1-2 form.
'9088{2}12{1}729'.split(/(?=\{)/)
.map(function (x) { return x.replace('{', '').replace('}', '-'); });
yields
["9088","2-12","1-729"]
I want to split a string into an array using "space and the comma" (" ,") as the separator. Through looking through some similar questions I figured out how to make them work as one separator. However I want them to work ONLY as one. So I do not want the array to be separated by only comma's or only spaces.
So I'd like the string "txt1, txt2,txt3 txt4, t x t 5" become the array txt1, "txt2,txt3 txt4", "t x t 5"
Here is my current code which doesn't do this:
var array = string.split(/(?:,| )+/)
Here is a link to the jsFiddle: http://jsfiddle.net/MSQxk/
Just do: var array = string.split(", ");
You can use this
var array = string.split(/,\s*/);
//=> ["txt1", "txt2", "txt3", "txt4", "t x t 5"]
This will compensate for strings like
// comma separated
foo,bar
// comma and optional space
foo,bar, hello
If you wanted to compensate for optional whitespace on each side of the comma, you could use this:
// "foo,bar, hello , world".split(/\s*,\s*);
// => ['foo', 'bar', 'hello', 'world']