JavaScript中提取特定字符之前的字符串的正则表达式

4

我有一个看起来像下面这样的字符串

str = "I have candy='4' and ice cream = 'vanilla'"

我想把术语移到等号左边,并且这些术语应该从最新的“= ”开始获取,直到出现另一个“= ”为止。

所以我的字符串应该是

leftOfEqual = "'4' and ice cream"

另一个例子

str = "I have candy='4' and ice cream = 'vanilla' and house='big'"

leftOfEqual = "'vanilla' and house"

这是我目前的正则表达式。
leftOfEqual = str.match(/\S+(?= *=)/)[0]

但是它只看第一个 =,然后只给我左边紧邻的单词。

我该怎么做?

注意: 如果在最新的 = 左边不存在,则应得到整个字符串直到开头的内容。


我们如何知道需要在等号左边的 ice cream 中包含 iceand 是用来分割的关键字吗? - Dane Brouwer
1
这个有帮助吗?尝试使用.*=(.*)=.*,并使用$1进行替换。 - user7571182
1
@Mandy8055 你最好将其作为答案添加,而不是评论。 - Dane Brouwer
1
@DaneBrouwer 这个想法是获取最后一个 = 左边到下一个 = 出现之间的字符串。 - Souvik Ray
1
你不能只是使用.split('=')吗? - user120242
显示剩余2条评论
5个回答

4

使用splitslice查找倒数第二个分组。
使用lastIndexOf来从后面进行搜索。找到第一个=,然后继续到下一个=,在它们之间进行切片。

str = "I have candy='4' and ice cream = 'vanilla'"
console.log(
str.split('=').slice(-2)[0]
)

console.log(
str.slice(str.lastIndexOf('=',x=str.lastIndexOf('=')-1)+1,x<-1?undefined:x)
)

str = "and ice cream = 'vanilla'"
console.log(
str.split('=').slice(-2)[0]
)

console.log(
str.slice(str.lastIndexOf('=',x=str.lastIndexOf('=')-1)+1,x<-1?undefined:x)
)

str = "I have cand'4' and ice cream 'vanilla'"
console.log(
str.split('=').slice(-2)[0]
)

console.log(
str.slice(str.lastIndexOf('=',x=str.lastIndexOf('=')-1)+1,x<-1?undefined:x)
)


这可能是最简单和最棒的解决方案 :) 为什么我没想到呢! - Souvik Ray
1
@JvdV 当然,我会的。我只是在测试不同的答案,并找出哪个最好用。很快就会接受。 - Souvik Ray
@user120242 我尝试了所有的情况,这个方法都有效,并且它也是最简单的。谢谢! - Souvik Ray

3

你可以尝试以下方法:

.*=(.*)=.*|(.*)=.*

以上正则表达式的解释:

.* - 贪婪地匹配除了换行符外的所有内容,直到 = 符号。

= - 匹配等于号 = 符号。

=(.*)= - 代表一个捕获组,捕获两个等于号之间的所有内容。如果你想要匹配多个不同符号,可以使用字符类,如 [=%#]

|(.*)=.* - 代表一个备用捕获组,表示在最新的 = 后面没有 = 的情况下等号左侧的内容。

$1$2 - 你可以使用此选项将整个字符串替换为所需的输出。

你可以在这里找到以上正则表达式的演示。


图示表示

const regex = /.*=(.*)=.*|(.*)=.*/g;
const str = `"I have candy='4' and ice cream = 'vanilla'"
I have candy='4' and ice cream = 'vanilla' and house='big'
Regex is fun
Regex is beauty =
Regex is awesome = test test test
`;
const subst = `$1$2`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);
// You can use trim if you want to get rid of previous or after spaces.
console.log(result);


如果您想逐行匹配,那么您需要使用^$。这将匹配整个字符串。您的正则表达式需要进行调整,以便在没有等号的情况下工作(我认为他在您评论解决方案后才添加了该要求?)。您可以使用[^=]来实现匹配。 - user120242
感谢@user120242的建议。但是我认为如果我使用replace,那么只有可能匹配的内容才会被替换。请查看我附加的示例代码片段。它适用于没有等号的字符串。如果我对您的评论理解有误,请纠正我。 - user7571182
1
啊,你使用了替换功能。我看错了。运行良好。 - user120242
1
@Mandy8055,你的解释很好。给你点赞。 - Souvik Ray

2

最终我认为你可以只使用splitreverse,再加上一个额外的trim

str = "I have candy='4' and ice cream = 'vanilla' and house='big'"
leftOfEqual = str.split('=').reverse()[1].trim();
console.log(leftOfEqual)

但是你必须使用正则表达式,可以使用类似于以下模式的模式:
[^=]+(?==[^=]*$)

查看在线演示

  • [^=]+ - 非等号字符,一次或多次
  • (?==[^=]*$) - 正向先行断言,等号后面为零个或多个非等号字符直到字符串结尾。

enter image description here


这也应该可以勾选:

“如果在最新的=左边没有出现=,我应该获得从开始到完整字符串。”


2
在您当前的模式\S+(?= *=)中,您正在匹配1个或多个非空白字符,并断言右侧是等号。
您也可以使用捕获组并匹配字符串末尾的最后一个=。
如果没有可用的第一组值,则返回匹配结果,匹配任何除换行符或=之外的字符。否则返回第一组的值。
^(?:.*=([^\r\n=]+)=[^=\r\n]+$|[^\r\n=]+)

解释

  • ^ 字符串的开始位置
  • .*= 匹配除换行符以外的任意字符0次或多次,直到最后一个等号 (=) 出现
  • [^\s=]+ 匹配出除了 - 或空白字符之外的任何字符
  • \s*=\s* 匹配可选空格字符之间的 =
  • ( 捕获 第一组
    • [^\r\n=]+ 匹配除了等号和换行符之外的任意字符至少一次
  • ) 关闭第一组
  • =[^=\r\n]+$ 匹配字符串末尾最后一个等号 (=)
  • |
  • [^\r\n=]+ 匹配除换行符和等号之外的任意字符至少一次

正则表达式演示

const pattern = /^(?:.*=([^\r\n=]+)=[^=\r\n]+$|[^\r\n=]+)/;
[
  "I have candy='4' and ice cream = 'vanilla'",
  "I have candy='4' and ice cream = 'vanilla' and house='big'",
  "test test ='test test test'"
].forEach(s => {
  console.log(s.match(pattern)[1] || s.match(pattern)[0]);
});


@JvdV 我在评论中看到,目前如果只有一个 =,它将返回其后的整个值。因此对于 test test ='test test test',它将返回 'test test test'。不过我可能是错的,也许这不是预期的结果。 - The fourth bird
@Thefourthbird 这就是我想知道的。第三个应该返回 test test - Souvik Ray
1
@JvdV 我明白你的意思,我认为在这种情况下你可以使用一个替代方案。我已经更新了它。 - The fourth bird
@SouvikRay 我明白你的意思了,我已经添加了一个更新。 - The fourth bird
1
@Thefourthbird 我现在明白了。感谢你详细解释正则表达式,给你点赞。 - Souvik Ray

1

你可以使用正则表达式的前后查找

const findData = (str) => {
  let data = str.match(/(?<==)([^=]+)(?==[^=]*$)/)
  return data ? data[1].trim() : ''
}

let str1 = "I have candy='4' and ice cream = 'vanilla' and house='big'"
let str2 = "I have candy='4' and ice cream = 'vanilla'"

console.log(findData(str1))
console.log(findData(str2))

// You can use split as well

console.log(str1.split('=').slice(-2)[0].trim())
console.log(str2.split('=').slice(-2)[0].trim())


提醒一下,如果我想在控制台中测试您的正则表达式,则您需要重新设计问题才能使其正常运行。虽然 split如前所述仍是一个不错的解决方案。 - JvdV
@JvdV 你是否使用不支持后行断言的浏览器?对我来说似乎运行良好。 - Code Maniac
刚才在谈论你写下的答案。看看如果你点击“运行”会发生什么 =)。 - JvdV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接