如何使用正则表达式忽略包含特定子字符串的字符串?

4
如何使用负回顾后发表达式(或其他方法)来忽略包含特定子字符串的字符串?
我阅读了两个之前的stackoverflow问题: java-regexp-for-file-filtering regex-to-match-against-something-that-is-not-a-specific-substring 它们几乎是我想要的...我的问题是字符串不以我想要忽略的内容结尾。如果这样做,这将不是一个问题。
我觉得这与环视是零宽度有关,第二次通过字符串时会匹配到某些内容...但是,我对内部机制并不确定。
无论如何,如果有人愿意花时间解释一下,我将非常感慕。
以下是我想要忽略的输入字符串的示例:
192.168.1.10 - - [08/Feb/2009:16:33:54 -0800] "GET /FOO/BAR/ HTTP/1.1" 200 2246

这是一个我想保留以供进一步评估的输入字符串示例:

192.168.1.10 - - [08/Feb/2009:16:33:54 -0800] "GET /FOO/BAR/content.js HTTP/1.1" 200 2246

对我来说关键是,我想忽略任何在文档根默认页面之后进行的HTTP GET。

以下是我的小测试工具和我迄今为止想出的最佳正则表达式。

public static void main(String[] args){
String inString = "192.168.1.10 - - [08/Feb/2009:16:33:54 -0800] \"GET /FOO/BAR/ HTTP/1.1\" 200 2246";
//String inString = "192.168.1.10 - - [08/Feb/2009:16:33:54 -0800] \"GET /FOO/BAR/content.js HTTP/1.1\" 200 2246";
//String inString = "192.168.1.10 - - [08/Feb/2009:16:33:54 -0800] \"GET /FOO/BAR/content.js HTTP/"; // This works
//String inString = "192.168.1.10 - - [08/Feb/2009:16:33:54 -0800] \"GET /FOO/BAR/ HTTP/"; // This works
String inRegEx = "^.*(?:GET).*$(?<!.?/ HTTP/)";
try {
  Pattern pattern = Pattern.compile(inRegEx);

  Matcher matcher = pattern.matcher(inString);

  if (matcher.find()) {
    System.out.printf("I found the text \"%s\" starting at " +
"index %d and ending at index %d.%n",
matcher.group(), matcher.start(), matcher.end());
  } else {
    System.out.printf("No match found.%n");
  }
} catch (PatternSyntaxException pse) {
  System.out.println("Invalid RegEx: " + inRegEx);
  pse.printStackTrace();
}
}

所以,您只对明确请求“文件”的内容感兴趣(例如/path/to/file.txt),而不是指向“目录”的内容(例如/path/to/)。唯一的要求是所请求的URI以某个“扩展名”结尾(例如您的示例中的.js)吗? - theraccoonbear
第一个问题回答正确。我只想要“文件”,不需要“目录”。文件名和扩展名并不重要... 我只想忽略对文档根目录的请求。 - Matt Cummings
4个回答

4

你能匹配任何不以/结尾的路径吗?

String inRegEx = "^.* \"GET (.*[^/]) HTTP/.*$";

这也可以使用“负回顾后断言”来完成。
String inRegEx = "^.* \"GET (.+)(?<!/) HTTP/.*$";

在这里,(?<!/) 表示“前面的序列必须匹配/”。

谢谢 Zack。这个完美地运行,我相信它比使用lookaround要好得多。现在,为了自己的学习,是否有可能使用lookaround和Java正则表达式引擎来实现? - Matt Cummings

1
也许我在这里漏掉了什么,但是你不需要任何正则表达式,只要忽略这个条件即可:
string.contains("/ HTTP")

因为文件路径不会以斜杠结尾。

0
我会使用类似这样的代码:
"\"GET /FOO/BAR/[^ ]+ HTTP/1\.[01]\""

这个匹配的是除了 /FOO/BAR/ 之外的所有路径。


-1

感谢您提供这些好的建议...很奇怪,我有Friedl的书和Habibi的书,但我太无知了,无法从阅读这些主题中分辨出整个负面回溯(总的来说是环视)。通常我可以从这两个来源获得大部分信息;但这一个让我感到困惑! - Matt Cummings
虽然这是一个有用的评论,但它并不是问题的答案。建议将其更改为评论。 - james.garriss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接