我正努力使用正则表达式。我想我了解个人的表达方式,但是将某些东西组合在一起完全使我感到困惑。我不了解如何使用与AND运算符等效的东西来将我想要的片段连接成一个“完整”的匹配表达式。
例如,我想将一个字符串拆分成一个数组,将<1>
到<57>
到</1>
到</57>
的任何值上断开。
所以,我认为我需要类似的东西:
( '<' or '<\/' ) and ( [1-9] or [1-4][0-9] or [5][0-7] ) and '>'
我可以单独使用<[1-4] [0-9]>或[1-4] [0-9]>,但是当与'|'一起使用时它返回部分匹配项,或者在完全匹配项之间返回未定义的值。
能不能告诉我我不明白的地方?附件是我的例子。
如果对第一个表达式单击“尝试”,它将在每个<21>
或</21>
之后产生空值。当我测试它时,它在console.log中打印为未定义。第二个表达式在每个标签之后产生<
和</
。我不明白这一点,更不用说如何在此问题的早期将更完整的表达式转换为regExp。
所需的输出是:
'This is a', '<21>', 'test', '<\/21>', '.'
谢谢。
添加
收到格奥尔格(Georg)对这个问题的回答后,我开始对转义这些标签的方法感兴趣,特别是因为当前仅在Chrome中不支持负向回溯。我的意思是,\<21>
将被视为常规文本,并且此时不会生成字符串拆分。如果您对类似内容感兴趣,则可能会发现Revo Defining Types, Streamlining Functions提供的我的后续问题的答案很有帮助。
let b, B = document.querySelectorAll('button');
for ( b of B ) b.addEventListener( 'click', split_str, false );
function split_str( evt )
{
let e = evt.currentTarget,
r = new RegExp( e.previousElementSibling.value ),
s = e.parentNode.previousElementSibling.value;
e.parentNode.lastElementChild.textContent = s.split(r);
}
div > div { border: 1px solid rgb(150,150,150); width: 500px; height: 200px;padding: 5px; }
input { border: 1px solid rgb(150,150,150); width: 500px; margin-bottom: 20px; padding:5px; }
<input type='text' value="This is a<21>test</21>.">
<div>
<input type='text' value="(<[1-4][0-9]>)|(<\/[1-4][0-9]>)"> <button>try</button>
<input type='text' value="((<|<\/)[1-4][0-9]>)"> <button>try</button>
<div></div>
</div>
答案 0 :(得分:2)
您几乎可以理解。其实就像用|
替换'or'并用串联替换and
一样简单。然后通过在每个组的开头添加?:
来确保组不匹配:
(?:<|<\/)(?:[1-9]|[1-4][0-9]|[5][0-7])>
MDN has an explanation on the interaction of split
and regex。但是简短的示例解释是:
'hi_joe'.split('_'); // ['hi', 'joe']
'hi_joe'.split(/_/); // ['hi', 'joe']
'hi_joe'.split(/(_)/); // ['hi', '_', 'joe']
'hi_joe'.split(/(?:_)/); // ['hi', 'joe']
每个评论的更新,如果您也希望在结果数组中使用<##>,则将正则表达式包装在另外一组括号中。
((?:<|<\/)(?:[1-9]|[1-4][0-9]|[5][0-7])>)
答案 1 :(得分:1)
好的,让我们从thingy开始。很好,但是从技术上讲,不需要在单个符号中加上[5]
[1-9] | [1-4][0-9] | 5[0-7]
(为清楚起见,在此处和下方使用空格)。
在第一部分中,类似a | ab
的更改在写为ab?
时读起来更好,即“ a,然后可选地是b`。这给了我们
< \/ ?
现在,您要查找的“ and”(或“ and then”)运算符在正则表达式语言中非常简单-没什么。也就是说,a and then b
就是ab
。
但是,如果我们像这样简单地组合两个部分
a x | y | z
这将是一个错误,因为|
的优先级较低,因此将其解释为
ax | y | z
这不是我们想要的。因此,我们需要将数字内容放入括号中,出于下面将要解释的原因,这些括号也必须不可捕获:
<\/? (?: [1-9] | [1-4][0-9] | 5[0-7] )
这与我们的定界符匹配,但是我们也需要介于两者之间的所有内容,因此我们将split
输入。 split
通常会返回与定界符不匹配的字符串数组:
"a,b,c".split(/,/) => a b c
如果我们也想包含定界符,则必须将其放置在捕获组中:
"a,b,c".split(/(,)/) => a , b , c
所以我们必须再次将所有内容包装在括号中:
( <\/? (?: [1-9] | [1-4][0-9] | 5[0-7] ) )
这就是?:
的原因-我们希望捕获全部内容,而不是数字部分。
将所有内容放在一起似乎可以解决问题:
s = "This is a<21>test</21>."
console.log(s.split(/(<\/?(?:[1-9]|[1-4][0-9]|5[0-7])>)/))
希望这可以说明一些问题
答案 2 :(得分:0)
我了解正则表达式的方式是,除非另有说明,例如一个OR子句,您定义为正则表达式的所有内容都为AND形式。 [a-z]
将匹配一个字符,而[a-z][a-z]
将匹配一个字符和另一个字符。
根据您的用例,可能需要以下正则表达式。如您所见,它捕获了<number></number>
之间的所有内容。
<[1-5][0-9]>([\s\S]*?)<\/[1-5][0-9]>
<[1-5][0-9]> matches <number> where number is between 00 and 59.
[\s\S]*? matches every single character there is, including new lines, between zero and unlimited times.
</[1-5][0-9]> matches </number> where number is between 00 and 59.
这是一个代码段,返回<number></number>
之间的所有内容。它将匹配项转换为数组,并获取第一个匹配项的第一个捕获组。第一个捕获组是<number></number>
之间的所有内容,如正则表达式本身的括号所示。
let str = '<10>Hello, world!</10>';
let reg = /<[1-5][0-9]>([\s\S]*?)<\/[1-5][0-9]>/g;
let matches = Array.from( str.matchAll(reg) );
console.log(matches[0][1]);