【问题标题】:Regex pattern to parse path with tabs and newlines?使用制表符和换行符解析路径的正则表达式模式?
【发布时间】:2019-03-08 02:17:12
【问题描述】:

我有一条路径dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext,我想一次处理一个段。对于每个段,我想知道它前面有多少个制表符,并且我想保持路径的其余部分完好无损。对于给定的示例

迭代 1:

Preceding tabs: 0
Segment: dir
Rest: \n\tsubdir1\n\tsubdir2\n\t\tfile.ext

迭代 2:

Preceding tabs: 1
Segment: subdir1
Rest: \n\tsubdir2\n\t\tfile.ext

迭代 3:

Preceding tabs: 1
Segment: subdir2
Rest: \n\t\tfile.ext

迭代 4:

Preceding tabs: 2
Segment: file.ext
Rest: ""

我想出的模式是((?<=\\R)\\h*)(\\H+)。但是,这给了我\tsubdir1\n 作为第一场比赛。我做错了什么?

【问题讨论】:

    标签: java regex regex-lookarounds regex-group


    【解决方案1】:

    由于所有部分都由行分隔符\n 分隔,您可以简单地使用.+ 来匹配它们,因为默认点. 无法匹配行分隔符,因此您确定它会在\n 之前停止(或任何其他行分隔符,如\r)。

    您还可以添加一些组以将选项卡与实际段分开,例如 named group (?<tabs>\t*) 以在每次匹配开始时匹配零个或多个选项卡。

    要在匹配后打印剩余的文本,只需在最后一个匹配字符的索引后添加子字符串(您可以通过Matcher#end 获取它)。

    要打印包含\n\t 的字符串(不是作为文字,而是作为一对反斜杠和字母),您可以手动将每个"\n" 替换为"\\n""\t""\\t" 或使用 org.apache.commons.lang 中的 StringEscapeUtils 之类的实用程序类,其中包含为我们执行此操作的 escapeJava 方法。

    所以你的代码看起来像:

    String path = "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext";
    Pattern p = Pattern.compile("(?<tabs>\t*)(?<segment>.+)");//dot can't match line separators
    Matcher m = p.matcher(path);
    int i = 1;
    while(m.find()){
        System.out.println("iteration: " + i++);
        System.out.println("Preceding tabs: " + (m.group("tabs").length()));
        System.out.println("Segment: " + m.group("segment"));
        System.out.println("Rest: "+ StringEscapeUtils.escapeJava(path.substring(m.end())));
        System.out.println();
    }
    

    输出:

    iteration: 1
    Preceding tabs: 0
    Segment: dir
    Rest: \n\tsubdir1\n\tsubdir2\n\t\tfile.ext
    
    iteration: 2
    Preceding tabs: 1
    Segment: subdir1
    Rest: \n\tsubdir2\n\t\tfile.ext
    
    iteration: 3
    Preceding tabs: 1
    Segment: subdir2
    Rest: \n\t\tfile.ext
    
    iteration: 4
    Preceding tabs: 2
    Segment: file.ext
    Rest: 
    

    【讨论】:

    • 几个 cmets:1) StringEscapeUtils 现在在 commons-text 中,commons-lang 中的那个已被弃用。 2) 要从字面上打印\n,请替换为\\\\n,而不是\\n
    • @AbhijitSarkar (1) 感谢更新,(2) 仅当您使用支持正则表达式的 replaceAll 时,其中 \ 是元字符并需要额外的转义。但是,如果您使用不支持正则表达式语法的 replace 并且 also 替换所有匹配项 replace("\n", "\\n") 应该可以正常工作。
    • 你是对的,关于replacereplacereplaceAll 实际上都替换了所有内容,这会更令人困惑吗?
    • @AbhijitSarkar 是的,替换方法的命名令人困惑。 All 后缀背后的可能原理是它强调了它与 replaceFrist 之间的区别,replaceFrist 也支持正则表达式语法。令人困惑的部分是其他替换方法:replace(char target, char replacement)replace(CharSequence target, CharSequence replacement) 不使用正则表达式,但 also 替换 all 出现的 target
    • 替代名称可能是 replaceRegexreplaceFirstRegex,IMO 不会那么混乱,但有些人可能会说这些名称可能太长(IMO 不是这种情况,因为 IDE 会建议它们和人会自动完成它们,所以我们真的不需要更多的击键)。但这只是我的看法。
    猜你喜欢
    • 2020-09-11
    • 1970-01-01
    • 2013-02-23
    • 1970-01-01
    • 2017-12-23
    • 2011-08-22
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多