英文:
Javascript: run specific parts of strings through a function
问题
我想解析一个字符串格式的数据。需要解析的字符串中任何被括号括起来的部分都应该被替换为通过一个函数运行后的结果。这是我想要的:
```javascript
function foo(str) {
return parseInt(str) + 1; // 举例的函数,实际函数可能不同
}
function parse(str) {
// 字符串中被括号括起来的部分应该被替换为通过foo()运行后的结果。
// 举例
// 输入: "我的名字是foo,我今年(0)岁。"
// 输出: "我的名字是foo,我今年1岁。"
// "(0)" 已经被替换为 foo("0") 的结果
}
我想出了一些不太好的解决方法,但我想要更健壮的方法。例如:
function parse(str) {
// 输入: "我的名字是foo,我今年(0)岁。"
str = str.replaceAll("(", "${foo('");
str = str.replaceAll(")", "')}");
str = "`" + str + "`";
// 现在 str 变成了 "`我的名字是foo,我今年${foo('0')}岁。`"
// 我可以使用 eval() 或其他方法来处理它,就像我手动输入了这个字符串一样
}
不过,这种方法并不是一个很好的做法。
编辑:我测试了一下,它可以工作,但是有一定的安全风险。
我想不出其他更好的方法,而且我不太擅长正则表达式。(虽然我会接受使用正则表达式的解决方案)
<details>
<summary>英文:</summary>
I want to parse some data that's in a string format. Anything enclosed in parenthesis in the string to parse should be replaced with itself run through a function. This is what I want:
function foo(str) {
return parseInt(str) + 1; // Example function, not actually what the function will be
}
function parse(str) {
// everything in str that is enclosed in parenthesis should be replaced with itself ran through foo();
// Example
// Input: "My name is foo and I am (0) year old."
// Output: "My name is foo and I am 1 year old."
// "(0)" has been replaced with the result of foo("0")
}
I have thought up a couple bad workarounds, but I want something more robust. For example:
function parse(str) {
// Input: "My name is foo and I am (0) year old."
str = str.replaceAll("(", "${foo('");
str = str.replaceAll(")", "')}");
str = "" + str + "
"
// Here str will be "My name is foo and I am ${foo(0)} year old.
"
// And I can use eval() or something to treat it like I've typed that
}
This, however, is kind of a bad way of doing it.
EDIT: I tested it, it works, but it is quite vulnerable.
I can't think of anything else and I'm not very good with RegEx. (although I'd accept a solution using it)
</details>
# 答案1
**得分**: 1
你可以使用完全匹配模式,并将结果字符串包装在反引号中,以便将其作为字符串文字进行评估。
```javascript
const foo = (value) => +value + 1;
const parse = (str) =>
'`' +
str.replace(/\((\w+)\)/g, (_, v) => `${foo(${v})}`) +
'`';
// Source: https://stackoverflow.com/a/29182787/1762224
console.log(eval(parse('My name is foo and I am (0) year old.')));
唯一的问题是匹配括号之间的模式似乎是任何类型的值。这可能会在以后造成问题。根据需要调整正则表达式。
如果您不想使用 eval
,可以传递一个回调函数:
const foo = (value) => +value + 1;
const parse = (str, callback) =>
str.replace(/\((\w+)\)/g, (_, v) => callback(v));
// Source: https://stackoverflow.com/a/29182787/1762224
console.log(parse('My name is foo and I am (0) year old.', foo));
英文:
You could used a full matching pattern, and wrap the resulting string in back-ticks so it's evaluated as a string literal.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const foo = (value) => +value + 1;
const parse = (str) =>
'`' +
str.replace(/\((\w+)\)/g, (_, v) => `${foo(${v})}`) +
'`';
// Source: https://stackoverflow.com/a/29182787/1762224
console.log(eval(parse('My name is foo and I am (0) year old.')));
<!-- end snippet -->
The only problem with this is that the pattern to match between the parenthesis seems to be any kind of value. This could pose problems down the road. Just tweak the regular expression as-needed.
If you don't want to use eval
, pass a callback:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const foo = (value) => +value + 1;
const parse = (str, callback) =>
str.replace(/\((\w+)\)/g, (_, v) => callback(v));
// Source: https://stackoverflow.com/a/29182787/1762224
console.log(parse('My name is foo and I am (0) year old.', foo));
<!-- end snippet -->
答案2
得分: 0
这是我会做的。我会使用正则表达式来匹配字符串中括号内的内容。然后,我将使用str.replaceAll()
函数将匹配到的字符串替换为foo()
函数的结果。
const regex = /\((\d*)\)/gm;
function foo(str) {
return parseInt(str) + 1;
}
function parse(str) {
// 循环匹配字符串中的正则表达式
let m;
while ((m = regex.exec(str)) !== null) {
// 避免与零宽匹配产生无限循环的必要操作
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// 将所有匹配的实例替换为匹配操作的结果
str = str.replaceAll(m[0], foo(m[1]))
}
return str;
}
let p = parse('My name is foo and I am (0) year old and I want (54) apples');
// 结果将是:My name is foo and I am 1 year old and I want 55 apples
这样,您就不需要使用eval()
,因为它可能对您的应用程序造成风险。
希望这对您有用。如果我漏掉了什么,请告诉我,我会编辑我的答案。
英文:
Here's what I would do. I would match the string with a RegEx that would match anything inside parenthesis in the string. With that, I would then use str.replaceAll()
to replace the matched string with the result of the foo()
function.
const regex = /\((\d*)\)/gm;
function foo(str) {
return parseInt(str) + 1;
}
function parse(str) {
// Loop all match the regex find in the string
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// Replace all instance of the match with the operation of the match
str = str.replaceAll(m[0], foo(m[1]))
}
return str;
}
let p = parse('My name is foo and I am (0) year old and I want (54) apples');
// The result will be: My name is foo and I am 1 year old and I want 55 apples
With that, you won't need to use eval()
as it potentially pose a risk for your application.
I hope that would work for you. If I missed anything, tell me, I will edit my answer.
答案3
得分: 0
请看看这是否适用于您:
function foo(str) {
return parseInt(str) + 1;
}
function parse(str) {
return str.replace(/\((\d+)\)/g, (_, num) => foo(num));
}
这个正则表达式模式匹配字符串中括号内的每个数字,将它们放在第一个捕获组中,并将它们全部传递给 foo()
。
英文:
See if it works for you:
function foo(str) {
return parseInt(str) + 1;
}
function parse(str) {
return str.replace(/\((\d+)\)/g, (_, num) => foo(num));
}
This Regex pattern matches every number in a string that is inside a parenthesis, put them in the 1st capturing grouping and pass all of them in foo()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论