用多个正则表达式模式拆分字符串会返回不需要的值
JavaScript - Splitting string by multiple regex patterns returns undesired values
设置
我有一个字符串,类似于:
Sample Strings
val4[3].sub1[ 1 ][2].smth.esl
// or
val4.sub1
// or
val4.sub1[2].smth
// and so on...
字符串将始终遵循以下规则:
- 字符串总是以属于
A-Za-z0-9_-
的字符开头 - 每个句号后面必须至少有一个
A-Za-z0-9_-
- 每个左括号
[
都有一个匹配的右括号]
- 每组括号包含一个整数,可选的前后空格
用与访问关联数组中的项相同的方式来考虑字符串。例如,上面列出的第一个字符串可能访问如下数组:
Sample Array Structure
val4 = [
0,
'some string',
2,
{
sub1: [
[1, 2, 3],
[
'val',
1,
{
smth: {
esl: 'final value'
}
}
],
[4, 5, 6]
],
sub2: 'another str'
},
4
];
, val4[3].sub1[ 1 ][2].smth.esl
处的值为final value
。
虽然数组是一个噩梦,但只是为了帮助理解输入字符串中可接受的模式。
预期行为
我要做的是按以下方式分割字符串:
句点及以下任何属于
A-Za-z0-9_-
的文本/'.([A-Za-z0-9_-]+)/g
带整型内容和可选前后空格的括号对
/'['s?['d]+'s?']/g
那么,再次以第一个字符串为例:
val4[3].sub1[ 1 ][2].smth.esl
会分裂成
Desired Output
val4
[3]
.sub1
[ 1 ]
[2]
.smth
.esl
您可以在这个RegExr中看到期望的分组应该是什么。
试验jsfield代码
当我运行以下命令时:
Code Block #1
var str = 'val4[3].sub1[ 1 ][2].smth.esl';
var re = /('['s?['d]+'s?'])|(?='.([A-Za-z0-9_-]+))/g;
var splits = str.split(re);
注意:在正则表达式中,我将第二个模式设置为正向前看(?=
),以便句点与
我以以下内容结束:
Output #1
splits = [
"val4",
"[3]",
null,
".sub1",
"[ 1 ]",
null,
"",
"[2]",
null,
".smth",
null,
"esl",
".esl"
];
结果非常接近,有几个明显的例外:
-
splits[2]
、splits[5]
、splits[8]
和splits[10]
为空 -
splits[6]
为空字符串 -
splits[11]
缺少前一个周期(并且实际上只是splits[12]
的错误副本)
只使用括号部分
运行 Code Block #2
var re = /('['s?['d]+'s?'])/g;
的回报:
Output #2
splits = [
"val4",
"[3]",
".sub1",
"[ 1 ]",
"",
"[2]",
".smth.esl"
];
用运行这个命令,只有的句号/字符部分
Code Block #3
var re = /(?='.([A-Za-z0-9_-]+))/g;
的回报:
Output #3
splits = [
"val4[3]",
".sub1[ 1 ][2]",
"smth",
".smth",
"esl",
".esl"
];
但是前面两种方法都有自己的缺点(空值,字符串不带句点)。
我以前用正则表达式说过"I'm so close",但离得太远了。但是,我觉得我正处在风口浪尖上。
那么,我如何修改正则表达式/分割来完成我所追求的?
基本上,不返回null或空值,只有字符串前面有的句点。
希望我已经说清楚了,如果有任何含糊之处请告诉我。
重要!
对于建议的解决方案,它需要是…
独立于浏览器的
这意味着ES6可能不会有任何变化,因为浏览器对新内容的支持非常不一致。不能强迫人们仅仅为了运行这个而采用浏览器
易于移植到PHP(首选,但不是绝对关键)
有一个为服务器端操作编写的姊妹脚本。避免使用javascript特有的技术将有助于在两种语言中实现
附加(非必需)
(对于那些对上下文和目的感兴趣的人)
剧透!确实存在一个数组。与上面定义的val4
不完全相同,但没有不同,并且从来没有两次相同。
val4 = [... and so on...];
提供一个字符串(必须是字符串类型)
str = 'val4[3].sub1[ 1 ][2].smth.esl';
返回值必须是val4
中的值,在str
中的地址。
var val4 = [... and so on...];
var str = 'val4[3].sub1[ 1 ][2].smth.esl';
var result = getItem(val4, str);
会返回
return val4[3].sub1[1][2].smth.esl;
如果你有一个很好的方法来做我想做的事情,而不需要所有的正则表达式,我很高兴听到它。但仍然对问题中提出的主要问题感兴趣。
我猜最后你想构建的就是这个。
我稍微扩展了Regex来解析像["lorem ipsum"]
//parses the path into an Array of keys
var parsePath = (function(){
var fetchParts = /'['s*('d+|"(?:''['s'S]|[^''"])+")'s*']|(?:'.|^)([A-Za-z_$][A-Za-z_$0-9]*)/g;
var isValid = new RegExp("^(?:" + fetchParts.source.replace(/'((?:'?':)?/g, "(?:") + ")+$", "")
return function(str){
var s = str == null? "": String(str).trim();
if(!isValid.test(s))
throw new Error("invalid path: "+JSON.stringify(str));
for(var m, keys = []; m = fetchParts.exec(s);)
keys.push(m[1]? JSON.parse(m[1]): m[2]);
return keys;
}
})();
//takes a path or an Array of keys and returns a function that resolves the path from the passed object.
//returns undefined if path can't be resolved;
//v1
var resolvePath = function(path){
var keys = Array.isArray(path)? path: parsePath(path);
return keys.reduceRight(
(nextFn, key) => obj => obj != null && key in obj? nextFn(obj[key]): void 0,
v => v
);
}
//v2
var resolvePath = function(path){
var keys = Array.isArray(path)? path: parsePath(path);
return function(obj){
for(var i=0; i<keys.length; ++i){
if(obj == null) return void 0;
obj = obj[keys[i]]
}
return obj;
}
}
//usage:
var getSmthEsl = resolvePath('val4[3].sub1[ 1 ][2]["lorem''nipsum"].smth.esl');
console.log("a", getSmthEsl({
val4: [
null, //0
null, //1
null, //2
{ //3
sub1: [
null, //0
[ //1
null, //0
null, //1
{ //2
"lorem'nipsum": {
smth: {
esl: {
sucess: true
}
}
}
}
]
]
}
]
}))
console.log("b", getSmthEsl({ val4: [] }))
比你想象的简单多了:
window.val4 = [
0,
'some string',
2,
{
sub1: [
[1, 2, 3],
[
'val',
1,
{
smth: {
esl: 'final value'
}
}
],
[4, 5, 6]
],
sub2: 'another str'
},
4
];
let ref = 'val4[3].sub1[ 1 ][2].smth.esl'
let result = window; // or 'global' in node
ref.replace(/('w+)|'['s*('d+)'s*']/g, (_, $1, $2) => result = result[$1 || $2]);
console.log(result)
对于这个作业,您需要能够动态设置对象属性。之前我已经为此目的编写了一个代码。Object.prototype.setNestedValue()
.
setNestedValue([prop1[, prop2[, prop3…]]]],value)完全像它的孪生getNestedValue()
一样工作,但最后一个参数是要设置的值。如果该属性不存在,它将根据所提供参数的类型创建一个对象或数组。同样,字符串类型实参将产生一个对象,而数字类型实参将产生一个相同大小的Array。
让我们看看代码。
Object.prototype.setNestedValue = function(...a) {
a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
: (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
this[a[0]].setNestedValue(...a.slice(1)))
: this[a[0]] = a[1];
return this;
};
var str = "val4[3].sub1[ 1 ][2].smth.esl",
arr = str.split(/'['s*('d+)'s*']|'./)
.filter(prop => prop)
.map(prop => Number.isNaN(+prop) ? prop : +prop)
.concat("final value");
result = {}.setNestedValue(...arr);
console.log(JSON.stringify(arr));
console.log(JSON.stringify(result,null,4));
我首先展示结果参数数组如何调用setNestedValue(...arr)
,然后是结果对象。
哦,我的错…我以为你想动态地构造对象,但是你喜欢从已经构造的对象中动态地获得嵌套值。Object.prototype.getNestedValue()
是这项工作的理想选择。我们已经构造了对象,所以让我们再次使用上面的代码,动态地获取嵌套的值。
Object.prototype.getNestedValue = function(...a) {
return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};
Object.prototype.setNestedValue = function(...a) {
a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
: (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
this[a[0]].setNestedValue(...a.slice(1)))
: this[a[0]] = a[1];
return this;
};
var str = "val4[3].sub1[ 1 ][2].smth.esl",
arr = str.split(/'['s*('d+)'s*']|'./)
.filter(prop => prop)
.map(prop => Number.isNaN(+prop) ? prop : +prop)
.concat("final value"),
myObj = {}.setNestedValue(...arr),
value;
arr.pop(); // lets remove the "final value" since now we will get it.
value = myObj.getNestedValue(...arr);
console.log(value);
- 监视函数从服务返回不起作用,但作用域函数起作用
- 如何在不需要单击按钮的情况下获取选项的值
- Javascript不需要的关闭行为
- 删除客户端浏览器上不需要的内容
- Firefox使用JQuery返回不正确的JSON
- 不允许在字段中输入不需要的字符
- 不需要的JSON响应
- 如何使图像适合TD,而不需要包装在不同的屏幕分辨率上
- 返回并重新加载页面时显示不需要的服务器端警报消息
- find()方法返回具有不需要的属性的对象
- Javascript split() Regex 表达式在 Chrome 中返回不需要的逗号
- 为什么 => { } 中的代码需要返回,而 => 中的内容不需要
- text在迭代JavaScript XML中返回不需要的空文本值的内容
- 为什么$http.Get不需要返回任何东西
- js返回不需要的值
- ScriptBundle+Optimization返回不需要的数字
- RegEx返回SyntaxError:无效正则表达式:/*/:不需要重复
- 用多个正则表达式模式拆分字符串会返回不需要的值
- 如何从一个页面返回到前一个页面,而不需要使用jquery或ajax单击任何按钮
- Javascript计算排列——为什么当我不复制数组时,我的代码返回不需要的解决方案?