Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 正则表达式用于匹配特殊字符(连字符与数字混合除外)_Java_Regex - Fatal编程技术网

Java 正则表达式用于匹配特殊字符(连字符与数字混合除外)

Java 正则表达式用于匹配特殊字符(连字符与数字混合除外),java,regex,Java,Regex,我们目前正在Java的replaceAll函数中使用[^a-zA-Z0-9]从字符串中去除特殊字符。我们注意到,当连字符与数字混合时,我们需要允许连字符 不匹配连字符的示例: 1-2-3 -1-23-4562 --1--2--3--4- --9--a--7 425-12-3456 将匹配连字符的示例: --a--b--c 沃尔玛 我们认为我们制定了一个正则表达式,以满足后一个标准,作为参考,但我们不知道如何将其与原始正则表达式结合起来[^a-zA-Z0-9] 我们希望对Lucene搜索字

我们目前正在Java的
replaceAll
函数中使用
[^a-zA-Z0-9]
从字符串中去除特殊字符。我们注意到,当连字符与数字混合时,我们需要允许连字符

不匹配连字符的示例:

  • 1-2-3
  • -1-23-4562
  • --1--2--3--4-
  • --9--a--7
  • 425-12-3456
匹配连字符的示例:

  • --a--b--c
  • 沃尔玛
我们认为我们制定了一个正则表达式,以满足后一个标准,作为参考,但我们不知道如何将其与原始正则表达式结合起来
[^a-zA-Z0-9]

我们希望对Lucene搜索字符串执行此操作,因为索引时的工作方式:

在连字符处拆分单词,除非标记中有数字,在这种情况下,整个标记将被解释为产品编号,并且不会拆分

你试过这个吗:


[^a-zA-Z0-9-]

一个正则表达式无法完成此操作。(嗯……可能是Perl语言。)

(编辑:好的,您可以使用可变长度的负lookbehind来实现,Java似乎可以(几乎是唯一的!);请参见Cyborgx37的答案。无论如何,在我看来,您不应该使用单个正则表达式来实现这一点。:)

你能做的就是把字符串分割成单词,然后分别处理每个单词。我的Java非常糟糕,因此这里有一些非常明智的Python:

#预编译一些正则表达式
看起来像产品号=重新编译(r'\A[-0-9]+\Z')
not_wordlike=重新编译(r'[^a-zA-Z0-9])
不是像单词一样的编译(r'[^-a-zA-Z0-9]')
#在不是字母、数字或连字符而是点的任何东西上拆分
#必须后跟空格
words=re.split(r'(?:[^-.a-zA-Z0-9]|[.]\s)+',字符串)
精简的单词=[]
用文字表示:
如果word中的“-”与产品编号不匹配(word):
stripped_word=not_wordlike.sub(“”,word)
其他:
#产品编号;允许破折号
条状词=非条状词或连字号sub(“”,word)
剥离单词。追加(剥离单词)
传递给lucene(''.join(剥离的单词))
当我使用
'wal-mart 1-2-3'
运行此命令时,我会返回
'walmart 1-2-3'


但老实说,上面的代码复制了Lucene标记器已经在做的大部分工作。我认为您最好只将
标准标记器
复制到您自己的项目中,并对其进行修改以满足您的需要。

这个问题很棘手,因为Java不允许在环顾中进行无限递归,这基本上就是您所需要的。我已经设定了100个字符的限制,你会看到,如果你希望单词更长,你可以增加这个限制

这应该起作用:

(?<![0-9]\S{0,100})[^a-zA-Z](?!\S{0,100}[0-9])|(?<=[0-9]\S{0,100})[^a-zA-Z0-9-](?=\S{0,100}[0-9])
上面的表达式将用零长度字符串替换有问题的字符,将呈现以下输出:

--9--a--7 walmart
您可以在这里尝试:

请注意,此表达式依赖于由空格(空格、制表符、换行符等)分隔的单词。其他字符,如逗号和分号,将使表达式将两个单词视为一个。例如“--9-a-0-”沃尔玛“将被视为一个单词

编辑我上次编辑的最后一段不正确。如果您想包含其他字符作为分隔符,我建议在第一遍中用空格替换它们(例如,将“,”替换为“”)


我主要是一名.NET程序员,否则我会为您提供使用此模式的完整Java代码。

请原谅我发布了第二个答案,而不是编辑第一个答案,但我不完全确定问题是否在于消除那些立即被字母包围的破折号,或者,如果目的是仅在根本不包含数字的字符串中消除破折号。此解决方案适用于后一种情况。我的另一个解决方案是前一种情况

这种模式

String newValue = myString.replaceAll("[^\\sA-Za-z0-9\\-]|((?<!\\S*\\d)-(?!\\S*\\d))", "");

String newValue=myString.replaceAll(“[^\\sA-Za-z0-9\\\-]|”(?我根据regex标记的文档添加了[java]标记:“请还包括一个指定您正在使用的编程语言或工具的标记。"只有在与数字组合时才允许使用连字符?因此'--9--a--7'将去掉连字符,但'--9--0--7'将被单独保留?我相信这两个示例都将被单独保留,因为Lucene引号指出,如果标记中有数字,标记器不会拆分连字符。因此'--9--a--7'和'--9--0--7'将被保留为alone,但不是“--a--b--c”?是的,这是完全正确的。我不知道这是否会起作用-OP似乎建议只允许连字符与数字组合。但不清楚。OP提供了一些附加信息-连字符仅在与数字组合时才允许。如果没有数字,则连字符必须仍然有效已删除。@Cyborgx37:谢谢,我会看一看并修改我的答案。你可以,但它并不漂亮。啊哈,聪明。似乎Java有一个极少数的正则表达式引擎,它在
中只允许固定长度的模式(?;这当然使它不太可能:)@Eevee-是的,根据..NET允许无限递归,所以我发现我经常不得不简化我的正则表达式以在其他风格中工作。令人印象深刻。即使是这种疯狂行为的始作俑者Perl,也从未实现过任意可变宽度的负回溯。不过,我很少碰到这种限制;你到底在做什么你“经常”点击:)@Eevee-还有其他的表达式.NET使用,比如基于命名捕获的if-else表达式,在这样的场景中非常有用。@Eevee-当你在lookahead中有一个lookahead时,这真是太疯狂了。.NET对你在lookahead中的内容没有任何限制。
String newValue = myString.replaceAll("[^\\sA-Za-z0-9\\-]|((?<!\\S*\\d)-(?!\\S*\\d))", "");