Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.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和正则表达式,需要将一些数据拆分为多个实体。在我的输入中,单引号字符(')指定实体的结尾,除非其前面有转义字符,即问号(?) 我的正则表达式是(?并且我正在使用扫描仪将输入拆分为单独的实体。因此以下情况可以正常工作: Hello'There becomes 2 entities: Hello and There Hello?'There remains 1 entity: Hello?'There 但是,当我遇到想要避开问号的情况时,它不起作用。因此: Hello??'

我正在使用Java和正则表达式,需要将一些数据拆分为多个实体。在我的输入中,单引号字符(')指定实体的结尾,除非其前面有转义字符,即问号(?)

我的正则表达式是
(?并且我正在使用扫描仪将输入拆分为单独的实体。因此以下情况可以正常工作:

Hello'There  becomes 2 entities: Hello and There
Hello?'There remains 1 entity:   Hello?'There
但是,当我遇到想要避开问号的情况时,它不起作用。因此:

Hello??'There     should become 2 entities:   Hello?? and There
Hello???'There    should become 1 entity:     Hello???'There
Hello????'There   should become 2 entities:   Hello???? and There
Hello?????'There  should become 1 entity:     Hello????'There
Hello?????There   should become 1 entity:     Hello????There
Hello??????There  should become 1 entity:     Hello?????There
因此,规则是如果有偶数个问号,后跟引号,则应将其拆分。如果有奇数个问号,则不应拆分

有人能帮我修改正则表达式(希望有解释!)来处理多个情况吗

谢谢


Phil

尝试此表达式以匹配偶数情况:
(?\?\?){01000})

  • (?\?\?){01000}
    表示这些组可以有0到1000个。请注意,您不能编写
    (?>\?\?)*
    ,因为表达式需要具有最大长度(最大组数)。但是,根据表达式的其余部分,应该能够将上限增加很多
  • [^\?](?>\?\?)…
    表示两个问号的组前面必须有字符,但不能有问号(否则您将匹配奇数)

您确定要使用正则表达式吗?如果字符串相对较小和/或执行时间不是大问题,则可以使用字符串生成器和循环来计算“?”的数量,例如

//您的字符串
String x=“你好?”'World'Hello?'World”;
StringBuilder sb=新的StringBuilder();
//保持你的分裂
ArrayList parts=新的ArrayList();
int questionmarkcount=0;
国际伊塞文;
for(char c:x.toCharArray()){
如果(c=='?'){
问号计数++;
sb.附加(c);
}else if(c=='\''){
_isEven=questionmarkcount%2;
//如果有偶数个'?,或者没有
如果(_isEven==0 | | questionmarkcount==0){
//添加当前拆分,重置?计数并清除字符串生成器
添加(sb.toString());
sb.删除(0,sb.length());
questionmarkcount=0;
}否则{
//附加问号,不需要拆分
sb.附加(c);
//从头开始数数
questionmarkcount=0;
}
}否则{
sb.附加(c);
}
}
添加(sb.toString());
循环结束时,parts ArrayList将保存所有拆分。如果“.

前面有个偶数的问号,则当前代码将被拆分。不要为此使用
split()
。这似乎是显而易见的解决方案,但匹配实体本身要比匹配分隔符容易得多。大多数支持正则表达式的语言都有内置的方法,比如Python的
findall()
或Ruby的
scan()
,但在Java中,我们仍然需要编写样板文件。下面是一个例子:

Pattern p = Pattern.compile("([^?']|\\?.)+");
String[] inputs = {
    "Hello??'There",
    "Hello???'There",
    "Hello????'There",
    "Hello?????'There",
    "Hello?????There",
    "Hello??????There"
};
for (String s : inputs)
{
  System.out.printf("%n%s :%n", s);
  Matcher m = p.matcher(s);
  while (m.find())
  {
    System.out.printf("  %s%n", m.group());
  }
}
输出:

你好???这里:
你好
那里
您好,这里是:
喂
您好,这里是:
你好
那里
您好,这里是:
喂,你在吗
你好?????这里:
喂,在那里
你好,这里:
喂,你好

Thomas使用的任意最大长度的噱头,除了是一个令人厌恶的黑客(无意冒犯,Thomas!),是不可靠的,因为他们不断地在处理这些东西的Pattern.java代码中引入bug。但不要将此解决方案视为另一种解决方法;lookbehinds永远不应该是你的首选,即使是在.NET这样的口味中,它们工作可靠且不受限制。

@yzernik这是一个非捕获原子组。如果你省略它,匹配将是
?“
而不是
,也就是说,如果你使用该表达式进行拆分,
Hello???那里的
将被拆分为
Hello
There
而不是
Hello???
那里的
。我不明白你为什么不使用*而不是{01000}“我在回答中解释了这一点。基本上,原因是Java的正则表达式引擎不喜欢任意长度的look behinds(或look aheads)。因此,您必须提供最大长度,这就是为什么提供1000的上限(尽管它可以更高)。-你自己试试看,你会得到这样一条信息,比如
非法模式:在索引21附近,Look-behind组没有明显的最大长度(索引21将是星号/星号之前的位置)。有关更多信息,请查看“重要注意事项”这里的部分:更正:Java的lookaheads不受lookbehind的限制。任何有效的正则表达式都可以在lookahead中使用,就像其他所有支持lookaheads的风格一样。“你好吗?”还有一个实体:你好吗?”你认为这是一个正确的例子,是吗?因为你还说“因此,规则是如果有奇数个问号,后面跟一个引号,它应该被拆分”…@ChrisBrautigam从其他例子中,我假设如果你有偶数个问号,后面跟一个引号,那么拆分应该发生。@Thomas哦,是这样的。谢谢,我会从这个角度回答。啊!我把问题搞错了!感谢大家发现我将更新问题,使其正确。谢谢艾伦。我使用了您的解决方案的一个稍加修改的版本,效果非常好。
Pattern p = Pattern.compile("([^?']|\\?.)+");
String[] inputs = {
    "Hello??'There",
    "Hello???'There",
    "Hello????'There",
    "Hello?????'There",
    "Hello?????There",
    "Hello??????There"
};
for (String s : inputs)
{
  System.out.printf("%n%s :%n", s);
  Matcher m = p.matcher(s);
  while (m.find())
  {
    System.out.printf("  %s%n", m.group());
  }
}