如何编写提取标签文本的正则表达式?

时间:2014-01-06 22:20:05

标签: java regex

我一直在尝试创建一个用空格替换制表符元素的程序(假设制表符相当于8个空格,其中一个或多个空格用非空白字符(字母)。

我开始通过以下方式从扫描仪中提取文件中的文本:

try {
    reader = new FileReader(file)
} catch (IOException io) {
    println("File not found")
}
Scanner scanner = new Scanner(reader);
scanner.usedelimiter("//Z");
String text = Scanner.next();

然后我尝试解析以下面带有ptrn1的标签结尾的文本片段,并用ptrn2提取每个片段的最后一个单词的长度:

Pattern ptrn1 = Pattern.compile(".*\\t, Pattern.DOTALL);
Matcher matcher1 = ptrn1.matcher(text);
String nextPiece = matcher1.group();
println(matcher1.group()); /* gives me the first substring ending with tab*/

但是:

Pattern ptrn2 = Pattern.compile("\\s.*\\t"); /*supposed to capture the last word in the string*/
Matcher matcher2 = ptrn2.matcher(nextPiece);
String lastword = matcher2.group();

最后一行给出了一个错误,因为它显然无法与模式("\\s.\*\\t")匹配。这最后一个正则表达式有问题,其意图是"任意数量的空格,后跟任意数量的字符,后跟一个制表符。虽然我无法找出它有什么问题。我尝试过("\\s*.+\\t")("\\s*.*\\t")("\s+.+\\t");仍然没有运气。

稍后,根据以下建议,我简化了代码并在其中包含了示例字符串。如下:

       import acm.program.*;
       import acm.util.*;
       import java.util.*;
       import java.io.*;
       import java.util.regex.*;

    public class Untabify extends ConsoleProgram {
        public void run(){
            String s = "Be plain,\tgood son,\tand homely\tin thy drift.\tRiddling\tconfession\tfinds but riddling\tshrift. ";            
                Pattern ptrn1 =Pattern.compile(".*?\t", Pattern.DOTALL);
                Pattern ptrn2 = Pattern.compile("[^\\s+]\t", Pattern.DOTALL);

                String nextPiece;

                Matcher matcher1 = ptrn1.matcher(s);

                while (matcher1.find()){                
                    nextPiece = matcher1.group();
                    println(nextPiece);
                    Matcher matcher2 = ptrn2.matcher(nextPiece);
                    println(matcher2.group());

               }
            }
    }

程序可变地崩溃,首先是在" println(matcher2.group())&#34 ;;并在下一次运行" public void run()"消息:"调试当前指令指针" (这是什么意思?)。

3 个答案:

答案 0 :(得分:1)

您无需双重转义制表符(即\\t); \t会很好。 \t被java String解析器解释为制表符,并且该制表符被发送到正则表达式解析器,该解析器将其解释为制表符。您可以查看this answer以获取更多信息。

此外,您应该使用Pattern.DOTALL,而不是Pattern.Dotall

答案 1 :(得分:1)

模式"\\s.*\\t"必须匹配单个空白字符(\s),后跟0个或多个字符(.*),后跟单个标签(\t)。如果要捕获最后一个单词和一个尾随选项卡,则应使用单词boundary escape \b

Pattern.compile("\\b.*\\b\t");

如果您不想匹配任何字符,可以将上面的.替换为使用\w或任何字词定义。

这是您用来匹配标签之前的任何字词的代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegEx {
    public static void main(String args[]) {
        String text = "ab cd\t ef gh\t ij";
        Pattern pattern = Pattern.compile("\\b(\\w+)\\b\t", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(text);
        while (matcher.find()) {
            System.out.println(matcher.group(1));
        }
    }
}

以上将输出

cd
gh

有关详情,请参阅Regular Expression Tutorial,尤其是Predefined Character ClassesBoundary Matchers部分。

您可以在Regex101上获得更多详细信息并尝试使用此正则表达式。

答案 2 :(得分:1)

查看示例字符串会很有用。如果您只想要标签前的最后一个单词,那么您可以使用:

([^\s]+)\t

注意()是将最后一个单词放在一个组中。 [^\s]+表示一个或多个非空格。