【问题标题】:Split a string on multiple characters在多个字符上拆分字符串
【发布时间】:2013-12-17 04:09:43
【问题描述】:

我想将一个句子拆分为多个字符之一(如下所列)。我的正则表达式能够基于大多数字符进行拆分,但不能基于 '[', ']' (打开和关闭方括号)。如果我将字符串 SPECIAL_CHARACTERS_REGEX 更改为 [ :;'=\\()!-\\[\\]],它将开始拆分字符串中的整数,而不是拆分方括号。如何在方括号而不是整数上拆分正则表达式('[]' 表示所有整数)。

另一个相关问题,有没有办法也从字符串中拆分数字?例如。 9pm 应拆分为9pm

This:

private static final String SPECIAL_CHARACTERS_REGEX = "[ :;'=\\()!-]";
String rawMessage = "let's meet tomorrow at 9:30p? 7-8pm? i=you go (no Go!) [to do !]"
String[] tokens = rawMessage.split(SPECIAL_CHARACTERS_REGEX);

Gives:

Input: let's meet tomorrow at 9:30p? 7-8pm? i=you go (no Go!) [to do !]
output: [let, s, meet, tomorrow, at, 9, 30p?, 7, 8pm?, i, you, go, , no, Go, , , [to, do, , ]]

还有,

This:

private static final String SPECIAL_CHARACTERS_REGEX = "[ :;'=\\()!-\\[\\]]";
String rawMessage = "let's meet tomorrow at 9:30p? 7-8pm? i=you go (no Go!) [to do !]"
String[] tokens = rawMessage.split(SPECIAL_CHARACTERS_REGEX);

Gives:
let's meet tomorrow at 9:30p? 7-8pm? i=you go (no Go!) [to do !]
[let, s, meet, tomorrow, at, , , , , p, , , , , pm, , i, you, go, , no, , o, , , , to, do]

预期输出:

{"let", "s", "meet", "tomorrow", "at", "9", "30", "p", "7", "8", "pm", "i", "you", "go", "no", "Go", "to", "do"}

【问题讨论】:

  • 你的预期输出是什么?
  • [] 在 reg exp 中具有特殊含义,如果您想将它们用作匹配的一部分,则需要对其进行转义
  • 我已经在帖子中添加了预期的输出。
  • 如何从字符串中拆分数字?例如。 “9pm”也需要拆分为“9”和“pm”。谢谢!

标签: java regex split


【解决方案1】:

如果您将破折号留在字符类的中间,您也需要将其转义。

但是,通过将其放置在角色类的开头或结尾来避免这种情况。此外,您不需要在此处转义 (),并且您可能希望在字符类之后使用量词,*+

更新:要获得预期的结果,您可以这样做。

private static final String SPECIAL_CHARACTERS_REGEX = "[ :;'?=()!\\[\\]-]+|(?<=\\d)(?=\\D)";
String rawMessage = "let's meet tomorrow at 9:30p? 7-8pm? i=you go (no Go!) [to do !]";
String[] tokens = rawMessage.split(SPECIAL_CHARACTERS_REGEX);
System.out.println(Arrays.toString(tokens));

正则表达式:

[ :;'?=()!\[\]-]+    any character of: ' ', ':', ';', ''', '?',
                       '=', '(', ')', '!', '\[', '\]', '-' (1 or more times)
 |                   OR
  (?<=               look behind to see if there is:
   \d                digits (0-9)
  )                  end of look-behind
   (?=               look ahead to see if there is:
    \D               non-digits (all but 0-9)
   )                 end of look-ahead

Working demo

输出

[let, s, meet, tomorrow, at, 9, 30, p, 7, 8, pm, i, you, go, no, Go, to, do]

【讨论】:

  • 更进一步...我怎样才能从字符串中拆分数字?例如。 “30pm”也需要拆分为“30”和“pm”。谢谢! ——
  • @user721998 另请参阅我对杰瑞回答的评论。
【解决方案2】:

将破折号放在末尾(或开头或转义),否则将被视为一系列字符:

[ :;'=\\()!\\[\\]-]

您的原始正则表达式匹配![ 之间的所有字符,其中包括数字、大写字母和一堆其他符号,例如() 等等。

为了得到你期望的结果,你可能会使用这样的东西:

[ ?:;'=\\()!\\[\\]-]+|(?<=\\d)(?=\\D)

(?&lt;=\d)(?=\D) 用于分隔数字和非数字(或者您可能还想使用[0-9][^0-9],这应该更有效/更快)

ideone demo

【讨论】:

  • 请注意,您必须将部分放在方括号之前 (?&lt;=\\d)(?=\\D);如果你把它们放在另一个顺序,即(?&lt;=\\d)(?=\\D)|[ ?:;'=\\()!\\[\\]-]+,结果会有所不同。这是因为' ''?' 等字符同时匹配字符集和\\D。将字符集放在首位将确保当看到其中一个字符时,它将被视为匹配字符集中的字符,因此被视为分隔符,而不是保留在结果中的“前瞻”。跨度>
【解决方案3】:

在正则表达式中使用它会在数字后跟字母的任何位置拆分:

(?<=\\d)(?=[A-Za-z])

我已经在模式中仅使用上述内容进行了测试。要将其添加到您已有的内容中,请使用 |在您的正则表达式中拆分上述 您已经拥有的内容:

String[] parts = s.split("[ :;'=()!\\[\\]-]+|(?<=\\d)(?=[A-Za-z])");

(使用 hwnd 的答案)。 ?&lt;= 是lookbehind,如果点后面的模式匹配则匹配,?= 是lookahead,如果点后面的模式匹配则匹配。

【讨论】:

    【解决方案4】:

    首先在字母数字组合之间引入空格,例如 8pm,然后根据 '[' 和 ']' 转义序列的特殊字符进行拆分:

    String rawMessage  = "let's meet tomorrow at 9:30pm 7-8pm? i=you go (no Go!) [to do !]";
    String rawMessage2 = rawMessage.replaceAll("(?<=[0-9])(?=[a-zA-Z])", " ");
    String[] tokens  = rawMessage2.split("[ :;'=()!\\[\\]]+");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 2023-03-08
      • 2021-06-23
      • 2020-04-17
      相关资源
      最近更新 更多