微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用贪婪令牌保留 REGEX 分隔符

如何解决使用贪婪令牌保留 REGEX 分隔符

美好的一天,

我正在用 Java 编写一个方程求值器,并使用 REGEX 来识别值,包括科学记数法,我在其中一个提要中找到了它(并略有采用),如下所示:

[\d.]+(?:E-?\d+)?

我遇到的问题是我想保留分隔值。我怎样才能做到这一点?我在 regex101.com 上玩过它,但是,当我使用向前看和向后看时,它会抱怨贪婪的令牌。

我在 StackOverflow 上找到了其他几个 REGEX,但找不到保留分隔符的一个

提前致谢!

解决方法

可能不是世界上最快的事情,但你可以做这样的事情

/**
 * Holds onto and supplies the supplied split delimiter(s) to the split
 * array elements.<br><br>
 * <p>
 * This method creates a Regular Expression (RegEx) that is to be placed
 * within a String.split() method to acquire the desired array
 * content.<br><br>
 *
 * @param inputString       (String) The string to split.<br>
 *
 * @param delimiterPosition (Integer) A integer value of either 0,1,or 2.
 *                          The specific value determines how the detected
 *                          delimiter types are placed within the array:<pre>
 *
 *      0       Delimiter as separate element:
 *              a;b;c;d = [a,;,b,c,d]
 *              Core regex is: .split("((?&lt;=;)|(?=;))")
 *              Lookahead and Lookbehind used.
 *
 *      1       Delimiter at end of each element except last:
 *              a;b;c;d = [a;,b;,c;,d]
 *              Core regex is: .split("(?&lt;=;)")
 *              Lookahead used only.
 *
 *      2       Delimiter at beginning of each element except first:
 *              a;b;c;d = [a,;b,;c,;d]
 *              Core regex is: .split("(?=;)")
 *              Lookbehind used only.</pre><br>
 *
 * If nothing is supplied then each character of the supplied input string
 * is split into the sting array.<br><br>
 *
 * If any supplied delimiters or delimiter characters happen to be RegEx
 * Meta Characters such as: ( ) [ ] { { \ ^ $ | ? * + . &lt; &gt; - = ! for
 * example then those delimiters must be Escaped with a Double Backslash
 * (ie: "\\+" ) when supplied otherwise an exception will occur.<br>
 *
 * @param delimiters        (1D String Array or one to multiple comma
 *                          delimited String Entries) Any number of string
 *                          delimiters can be supplied as long as they are
 *                          separated with a comma (,).<br>
 *
 * @return (String) The Regular Expression (RegEx) to be used within a
 *         String.split() method.
 */
public static String[] SplitAndKeepDelimiters(String inputString,int delimiterPosition,String... delimiters) {
    if (delimiters.length < 1) {
        return inputString.split("");
    }

    // build regex...
    String regEx = "";
    for (int i = 0; i < delimiters.length; i++) {
        switch (delimiterPosition) {
            case 0:
                regEx += regEx.isEmpty() ? "((?<=" + delimiters[i] + ")|(?=" + delimiters[i] + "))"
                        : "|((?<=" + delimiters[i] + ")|(?=" + delimiters[i] + "))";
                break;
            case 1:
                regEx += regEx.isEmpty() ? "(?<=" + delimiters[i] + ")"
                        : "|(?<=" + delimiters[i] + ")";
                break;
            case 2:
                regEx += regEx.isEmpty() ? "(?=" + delimiters[i] + ")"
                        : "|(?=" + delimiters[i] + ")";
                break;
        }
    }
    return inputString.split(regEx);
}

上述方法将允许您拆分多个分隔符。

,

代替使用 split,您可以使用交替来获取匹配项,或者匹配第一个模式后面没有直接跟随的所有字符。

=== TASKFORM.JS ===

import React,{ useState,useEffect,useRef } from 'react'

function TaskForm(props) {

    const [input,setInput] = useState(props.edit ? props.edit.value : '');

    const inputRef = useRef(null);

    useEffect(() => {
        inputRef.current.focus()
    })

    const handleChange = e => {
        setInput(e.target.value);
    }

    const handleSubmit = e => {
        e.preventDefault();
        props.onSubmit({
            id: Math.floor(Math.random() * 1000),text: input
        });

        setInput('');

    };


    return (
        <form className="task-form" onSubmit={handleSubmit}>
            {props.edit ? (
                <>
                <input type="text" placeholder="Update your task" value={input} name="text" className="task-input" onChange={handleChange} ref={inputRef}/>
                <button className="task-button edit" onChange={handleChange}>Update a task</button>
                </>
            ) : (
                <>
                <input type="text" placeholder="Add a new task" value={input} name="text" className="task-input" onChange={handleChange} ref={inputRef}/>
                <button className="task-button" onChange={handleChange}>Add a task</button>
                </>
            )}
            
        </form>
    )
}

export default TaskForm

模式匹配:

  • [\d.]+(?:E-?\d+)?|(?:(?![\d.]+(?:E-?\d+)?).)+ 科学记数法的模式
  • [\d.]+(?:E-?\d+)?
  • | 非捕获组
    • (?: 负向前瞻,当科学记数法不在右边时匹配单个字符
  • (?![\d.]+(?:E-?\d+)?). 关闭非捕获组,重复 1+ 次以匹配至少一个字符

Regex demo | Java demo

例如

)+

输出

String regex = "[\\d.]+(?:E-?\\d+)?|(?:(?![\\d.]+(?:E-?\\d+)?).)+";
String string = "cos(2123.324E3)*ln(e^x)+123.345E-6*sin(sin(sin(x)))";

Pattern pattern = Pattern.compile(regex,Pattern.MULTILINE);
Matcher matcher = pattern.matcher(string);

while (matcher.find()) {
    System.out.println(matcher.group(0));
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。