Javascript 将字符串与正则表达式部分匹配
假设我有一个正则表达式:/abcd/ 假设我想对照正则表达式检查用户输入,并且不允许在输入中输入无效字符。当用户输入“ab”时,它与正则表达式匹配失败,但我不能禁止输入“a”和“b”,因为用户不能同时输入所有4个字符(复制/粘贴除外)。所以我这里需要的是一个部分匹配,它检查一个不完整的字符串是否可能与正则表达式匹配 Java有这样的功能:Javascript 将字符串与正则表达式部分匹配,javascript,regex,Javascript,Regex,假设我有一个正则表达式:/abcd/ 假设我想对照正则表达式检查用户输入,并且不允许在输入中输入无效字符。当用户输入“ab”时,它与正则表达式匹配失败,但我不能禁止输入“a”和“b”,因为用户不能同时输入所有4个字符(复制/粘贴除外)。所以我这里需要的是一个部分匹配,它检查一个不完整的字符串是否可能与正则表达式匹配 Java有这样的功能:.hitEnd()(此处描述)python不是以本机方式执行此操作的,但它有一个执行此任务的包: 我没有在js中找到任何解决方案。多年前有人问: 甚至在此之前:
.hitEnd()
(此处描述)python不是以本机方式执行此操作的,但它有一个执行此任务的包:
我没有在js中找到任何解决方案。多年前有人问:
甚至在此之前:
p.S.正则表达式是自定义的,假设用户自己输入正则表达式,然后尝试输入与该正则表达式匹配的文本。这个解决方案应该是一个通用的解决方案,适用于运行时输入的正则表达式。我认为您必须有两个正则表达式,一个用于键入
/a?b?c?d?/
,另一个用于粘贴或保留输入时的最后测试/abcd/
这将测试有效的电话号码:
const input=document.getElementById('input'))
让oldVal=''
input.addEventListener('keyup',e=>{
if(/^\d{0,3}-?\d{0,3}-?\d{0,3}$/.test(e.target.value)){
oldVal=e.target.value
}否则{
e、 target.value=oldVal
}
})
input.addEventListener('blur',e=>{
console.log(/^\d{3}-?\d{3}-?\d{3}-?$/.test(e.target.value)?“有效”:“无效”)
})
我强烈怀疑(尽管我不是100%确定)这个问题的一般情况没有与著名的图灵“哈尔丁问题”相同的解决方法(参见)。即使有一个解决方案,它也很可能不是用户真正想要的,因此取决于你的严格程度将导致糟糕到可怕的用户体验
例如:
假设“target RegEx”是[a,b]*c[a,b]*
,也假设您第一眼看到的“test RegEx”[a,b]*c?[a,b]*
(显然字符串中的两个c
是无效的,是吗?)并假设当前用户输入是aabcbb
,但存在输入错误,因为用户实际需要的是aacbbb
。有许多可能的方法可以修复此打字错误:
- 删除
并在第一个c
之前添加它-将正常工作b
- 先删除
并在b
之后添加-可以正常工作c
- 首先在
之前添加b
,然后删除旧的-Oops,我们禁止此输入为无效,用户会发疯,因为没有正常人能够理解这样的逻辑李>c
注意,您的<代码> HITENT/COD>在这里会遇到同样的问题,除非您禁止用户在输入框中间输入字符,否则将成为另一种可怕的UI。 在现实生活中,会有许多更复杂的例子,你的任何智能启发法都无法正确解释,从而会让用户感到不安
那怎么办呢?我认为你能做的唯一一件事是你能做的最简单的事情,也就是说,只需分析你的“目标正则表达式”中的一组允许字符,并使你的“测试正则表达式”
[set of allowed chars]*
。是的,如果“target RegEx”包含
通配符,您将无法进行任何合理的筛选。对于那些认为根本没有解决方案的人来说,这是一个艰难的解决方案:在js中实现python版本()。所以这是可能的。如果有人有更简单的答案,他会赢得赏金
使用python模块(带反向引用的正则表达式)的示例:
$pip安装regex
$python
>>>导入正则表达式
>>>regex.regex(r'^(\w+\s+\1$).fullmatch('abcd-ab',partial=True)
看起来你很幸运,我已经在JS中实现了这些东西(它适用于大多数模式——也许这对你来说就足够了)。看见您还可以在那里找到一个可用的演示
这里不需要复制完整的代码,我只说明整个过程:
- 解析输入正则表达式,并执行一些替换。不需要错误处理,因为JS中的
对象中不能有无效模式RegExp
- 将
替换为abc
(?:a |$)(?:b |$)(?:c |$)
- 对任何“原子”都要这样做。例如,字符组
将变成[a-c]
(?:[a-c]|$)
- 保持锚的原样
- 保持消极的样子
如果JavaScript具有更高级的正则表达式特性,那么这种转换可能就不可能了。但由于其有限的功能集,它可以处理大多数输入正则表达式。如果输入字符串在回溯引用的中间结束(如匹配<代码> ^(\W+)s++1 $ < /代码>反对<代码> Hello HEL < /代码>),它将在ReGEX上产生不正确的结果。 < P>你们可能会发现这个感兴趣的页面: () 这是一项勇敢的努力:制作一个支持的WebAssembly实现。我还在玩它,但我怀疑它不实用。WebAssembly二进制文件的重量约为300K;如果JS意外终止,那么最终可能不会破坏模块,从而导致大量内存泄漏 底线是:这显然是ECMAscript人员应该正规化的东西,浏览器制造商应该提供的东西(WebAssembly开发人员可能会羞辱他们,让他们上当…) 我最近尝试使用输入[type='text']元素的“pattern”属性。一、 和其他许多人一样,我发现这是一个令人失望的问题,它在提交表单之前不会进行验证。因此,一个人将浪费时间键入(或粘贴…)大量字符并跳转到其他字段,结果在表单提交后发现他们输入的字段错误。理想情况下,我希望它
$ pip install regex
$ python
>>> import regex
>>> regex.Regex(r'^(\w+)\s+\1$').fullmatch('abcd ab',partial=True)
<regex.Match object; span=(0, 7), match='abcd ab', partial=True>
<input id="forward_address"
name="forward_address"
type="text"
maxlength="90"
pattern="^(bc(0([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59})|1[ac-hj-np-z02-9]{8,87})|[13][a-km-zA-HJ-NP-Z1-9]{25,34})$"
data-entry-templates="['bc099999999999999999999999999999999999999999999999999999999999','bc1999999999999999999999999999999999999999999999999999999999999999999999999999999999999999','19999999999999999999999999999999999']"
onkeydown="return validatePattern(event)"
onpaste="return validatePattern(event)"
required
/>
<input id="forward_address"
name="forward_address"
type="text"
maxlength="{{MAX_BTC_ADDRESS_LENGTH}}"
pattern="{{BTC_ADDRESS_REGEX}}" {# base58... #}
data-entry-templates="{{BTC_ADDRESS_TEMPLATES}}" {# base58... #}
onkeydown="return validatePattern(event)"
onpaste="return validatePattern(event)"
required
/>