【问题标题】:How to avoid greedy or non-specific regex?如何避免贪婪或非特定的正则表达式?
【发布时间】:2013-11-30 06:26:50
【问题描述】:

//---------为清晰而编辑--------//

我查看了网络的其余部分,但到目前为止,没有任何答案能满足我的问题。我有一个正则表达式,对于我正在尝试做的事情来说有点太贪婪了。例如,下面的正则表达式:

(?<piece>q|k|b|p|n|r+)(?<color>l|d)(?<x>\\w)(?<y>\\d)

将匹配

rdh8

rda6

rla1 a3

rlb2

但是,我需要我的正则表达式是具体的;我需要它来排除“rla1 a3”。 目前,正则表达式匹配rla1 a3 的“rla1”部分。由于'a3',我需要正则表达式完全忽略'rla1 a3'。

我尝试了诸如\s?$ 之类的解决方案,但这些都没有奏效。有什么想法吗?

*编辑* //------------------------------------------------ ------------------------------//

这里是问题的一些示例代码。

public ArrayList<String> theStringsToBeRead = new ArrayList<String>();

public void addLines() throws IOException
{
    String line;
    BufferedReader br = new BufferedReader(new FileReader("testFile"));

    //put each line into an arraylist
    while((line = br.readLine()) != null) 
    {
        theStringsToBeRead.add(line.toLowerCase()); //adds each line to the arraylist
    }
    //parse each line in arraylist
    for(String item : theStringsToBeRead)
    {
        testing(item); //for each line, run a regex check
    }
}

public void testing(String item)
{

    String regex = "(?<piece>q|k|b|p|n|r+)(?<color>l|d)(?<x>\\w)(?<y>\\d)";
    //String StevesRegex = "^(?<piece>q|k|b|p|n|r+)(?<color>l|d)(?<x>\\w)(?<y>\\d)$";  //doesnt appear to work
    Matcher m = Pattern.compile(regex).matcher(item);

    while (m.find()) 
    {
        System.out.println(m.group("piece")+m.group("color")+m.group("x")+m.group("y"));
    }   
}

文本文件为:

rdh8
rda6
rla1 a3
rlb2

我得到的输出是:

rdh8
rda6
rla1
rlb2

想要的结果是正则表达式完全忽略所有“rla1 a3”,而不是匹配其中的一部分。所需的输出将是:

rdh8
rda6
rlb2

任何帮助将不胜感激,非常抱歉让任何人对这个问题感到困惑。感谢您的耐心等待。

【问题讨论】:

  • 你有点不清楚。您是否只尝试每行匹配一个条目?如果还有更多,那你不想匹配?
  • 输入输出应该是什么?目前还不清楚
  • 抱歉,请检查编辑。这更清楚。
  • * 是文本的一部分,还是您要使其斜体?请删除所有突出显示的元字符并使用代码格式(缩进 4 个空格)来处理需要为文字的内容。
  • "rdh8" 和 "rla1 a3" 是我要匹配的两个单独的字符串。但是,目标是创建一个匹配第一个但排除第二个的正则表达式。

标签: java regex


【解决方案1】:

您的问题有点不清楚,但是如果您只想在输入的开头进行匹配,那么以下就足够了:

String regex = "^(?<piece>q|k|b|p|n|r+)(?<color>l|d)(?<x>\\w)(?<y>\\d)$";

^ 表示“在行首” $ 表示“行尾”

这是一个link 在线测试。

编辑
您的问题是由于空格引起的,要删除字符串前后的空格,请使用.trim(),即:

String s = br.readLine().trim().toLowerCase();

或者,您可以更改正则表达式以解释空格,如下所示:

String regex = "^\\s*(?<piece>q|k|b|p|n|r+)(?<color>l|d)(?<x>\\w)(?<y>\\d)\\s*$";

【讨论】:

  • 我需要正则表达式来匹配第一项但排除第二项。
  • 它会,但如果我有一个字符串列表,它只会匹配第一个字符串。此外,如果我将“rla1 a3”作为列表中的第一项,这个正则表达式仍然会匹配它。我需要让正则表达式排除后面带有其他字母/数字的任何项目
  • 如果我有一个 blc1、rla1 a3、nlb1、blc1 的列表,我的目标是让正则表达式只匹配最后两个和第一个。您的正则表达式仅匹配列表中的第一项。如果我将“rla1 a3”设为列表中的第一个,它将匹配“rla1”部分。由于尾随“a3”,我需要正则表达式完全拒绝“rla1 a3”上的匹配。
  • 我的要求,最后一次,如果它们没有意义,请纠正我:我需要正则表达式来拒绝任何带有尾随空格/字母/数字的项目。 --- 例如,“rla2”将是匹配项,而“rla2 a4”由于“a4”而被完全拒绝为匹配项。 ----- 这有意义吗?
  • @user2453973 我希望情况并非如此。对不起,你不是在拖钓。问题是每个字符串的末尾(或字符串的开头)很可能有换行符或某种空格。对字符串使用.trim() 命令。这将删除字符串前后的空格。
【解决方案2】:

在我看来,这部分正则表达式与 rdh8 匹配:

(?<piece>q|k|b|p|n|r+)(?<color>l|d)(?<x>\\w)(?<y>\\d)

这是匹配rla1 a3的部分:

\s+(.*?)

如果您希望您的正则表达式仅匹配它找到的第一个表达式并停止匹配,请尝试从正则表达式末尾删除 \s+(.*?)

【讨论】:

  • 对不起,我忘了删除我的正则表达式中的那部分。编辑后的正则表达式是给我带来麻烦的那个。 "\s+(.*?)" 之前的尝试没有成功。
  • 简而言之,删除 \s+(.*?) 没有效果,正则表达式的其余部分仍然匹配这两个项目的一部分。我需要正则表达式来匹配第一项但排除第二项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 2011-04-27
  • 2010-10-20
相关资源
最近更新 更多