Javascript 将字符串与正则表达式部分匹配

Javascript 将字符串与正则表达式部分匹配,javascript,regex,Javascript,Regex,假设我有一个正则表达式:/abcd/ 假设我想对照正则表达式检查用户输入,并且不允许在输入中输入无效字符。当用户输入“ab”时,它与正则表达式匹配失败,但我不能禁止输入“a”和“b”,因为用户不能同时输入所有4个字符(复制/粘贴除外)。所以我这里需要的是一个部分匹配,它检查一个不完整的字符串是否可能与正则表达式匹配 Java有这样的功能:.hitEnd()(此处描述)python不是以本机方式执行此操作的,但它有一个执行此任务的包: 我没有在js中找到任何解决方案。多年前有人问: 甚至在此之前:

假设我有一个正则表达式:/abcd/ 假设我想对照正则表达式检查用户输入,并且不允许在输入中输入无效字符。当用户输入“ab”时,它与正则表达式匹配失败,但我不能禁止输入“a”和“b”,因为用户不能同时输入所有4个字符(复制/粘贴除外)。所以我这里需要的是一个部分匹配,它检查一个不完整的字符串是否可能与正则表达式匹配

Java有这样的功能:
.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
    之前添加
    c
    ,然后删除旧的-Oops,我们禁止此输入为无效,用户会发疯,因为没有正常人能够理解这样的逻辑

注意,您的<代码> 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
/>