正则表达式,用于在未被单引号或双引号括起时使用空格分割字符串

java regex split

77883 观看

14回复

1249 作者的声誉

我是正规表达的新手,非常感谢你的帮助。我正在尝试将一个表达式组合在一起,该表达式将使用未被单引号或双引号括起的所有空格分割示例字符串。我的最后一次尝试看起来像这样:(?!")并不是很有效。在报价之前,它正在拆分空间。

输入示例:

This is a string that "will be" highlighted when your 'regular expression' matches something.

期望的输出:

This
is
a
string
that
will be
highlighted
when
your
regular expression
matches
something.

请注意"will be"'regular expression'保留单词之间的空格。

作者: carlsz 的来源 发布者: 2008 年 12 月 14 日

回应 14


1

96650 作者的声誉

搜索字符串,抓取每个部分,而不是拆分它可能会更容易。

原因是,您可以在前后空格处拆分"will be"。但是,我想不出任何指定忽略分裂内部空间的方法。

(不是实际的Java)

string = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";

regex = "\"(\\\"|(?!\\\").)+\"|[^ ]+"; // search for a quoted or non-spaced group
final = new Array();

while (string.length > 0) {
    string = string.trim();
    if (Regex(regex).test(string)) {
        final.push(Regex(regex).match(string)[0]);
        string = string.replace(regex, ""); // progress to next "word"
    }
}

此外,捕获单引号可能会导致问题:

"Foo's Bar 'n Grill"

//=>

"Foo"
"s Bar "
"n"
"Grill"
作者: Jonathan Lonowski 发布者: 2008 年 12 月 14 日

1

25110 作者的声誉

String.split()在这里没有用,因为没有办法区分引号内的空格(不拆分)和外部(拆分)的空格。Matcher.lookingAt()可能是你需要的:

String str = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
str = str + " "; // add trailing space
int len = str.length();
Matcher m = Pattern.compile("((\"[^\"]+?\")|('[^']+?')|([^\\s]+?))\\s++").matcher(str);

for (int i = 0; i < len; i++)
{
    m.region(i, len);

    if (m.lookingAt())
    {
        String s = m.group(1);

        if ((s.startsWith("\"") && s.endsWith("\"")) ||
            (s.startsWith("'") && s.endsWith("'")))
        {
            s = s.substring(1, s.length() - 1);
        }

        System.out.println(i + ": \"" + s + "\"");
        i += (m.group(0).length() - 1);
    }
}

产生以下输出:

0: "This"
5: "is"
8: "a"
10: "string"
17: "that"
22: "will be"
32: "highlighted"
44: "when"
49: "your"
54: "regular expression"
75: "matches"
83: "something."
作者: Zach Scrivena 发布者: 2008 年 12 月 14 日

0

19659 作者的声誉

我有理由相信单独使用正则表达式是不可能的。检查某些其他标记内是否包含某些内容是解析操作。这似乎与尝试使用正则表达式解析XML一样 - 它无法正确完成。您可以通过重复应用与引用的字符串匹配的非贪婪,非全局正则表达式来获得所需的结果,然后一旦找不到任何其他内容,将其拆分为空格...问题,包括跟踪所有子串的原始顺序。你最好的选择就是编写一个非常简单的函数来迭代字符串并拉出你想要的标记。

作者: rmeador 发布者: 2008 年 12 月 14 日

12

35903 作者的声誉

StackOverflow上有几个问题在使用正则表达式的各种上下文中涵盖了同一个问题。例如:

更新:示例正则表达式处理单引号和双引号字符串。参考:我怎样才能拆分字符串,除非在引号内?

m/('.*?'|".*?"|\S+)/g 

使用快速Perl片段对此进行测试,输出如下所示。如果它们在引号之间(不确定是否需要),也适用于空字符串或仅空白字符串。

This
is
a
string
that
"will be"
highlighted
when
your
'regular expression'
matches
something.

请注意,这确实包括匹配值中的引号字符本身,但您可以使用字符串替换删除它,或修改正则表达式不包括它们。我现在将其留作读者或其他海报的练习,因为凌晨2点已经太晚了,不能再乱用正则表达了;)

作者: Jay 发布者: 2008 年 12 月 14 日

5

5102 作者的声誉

如果要在字符串中允许转义引号,可以使用以下内容:

(?:(['"])(.*?)(?<!\\)(?>\\\\)*\1|([^\s]+))

引用的字符串将是第2组,单个未引用的字符将是第3组。

你可以在这里尝试各种字符串:http//www.fileformat.info/tool/regex.htmhttp://gskinner.com/RegExr/

作者: mcrumley 发布者: 2008 年 12 月 14 日

224

17390 作者的声誉

决定

我不明白为什么所有其他人都在提出如此复杂的正则表达式或如此长的代码。从本质上讲,您希望从字符串中获取两种内容:不是空格或引号的字符序列,以及以引号开头和结尾的字符序列,两种引号之间没有引号。您可以使用此正则表达式轻松匹配这些内容:

[^\s"']+|"([^"]*)"|'([^']*)'

我添加了捕获组,因为您不希望列表中的引号。

此Java代码构建列表,添加捕获组(如果匹配以排除引号),并在捕获组不匹配时添加整体正则表达式匹配(未匹配的单词匹配)。

List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
    if (regexMatcher.group(1) != null) {
        // Add double-quoted string without the quotes
        matchList.add(regexMatcher.group(1));
    } else if (regexMatcher.group(2) != null) {
        // Add single-quoted string without the quotes
        matchList.add(regexMatcher.group(2));
    } else {
        // Add unquoted word
        matchList.add(regexMatcher.group());
    }
} 

如果您不介意在返回的列表中使用引号,则可以使用更简单的代码:

List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
    matchList.add(regexMatcher.group());
} 
作者: Jan Goyvaerts 发布者: 2008 年 12 月 14 日

2

29 作者的声誉

(?<!\G".{0,99999})\s|(?<=\G".{0,99999}")\s

这将匹配未被双引号括起的空格。我必须使用min,max {0,99999},因为Java不支持*和+在lookbehind中。

作者: Marcus Andromeda 发布者: 2010 年 9 月 15 日

1

5255 作者的声誉

我喜欢Marcus的方法,但是,我修改它以便我可以在引号附近允许文本,并支持“和'引用字符。例如,我需要一个=”某个值“不将它分成[a =,”一些价值“]。

(?<!\\G\\S{0,99999}[\"'].{0,99999})\\s|(?<=\\G\\S{0,99999}\".{0,99999}\"\\S{0,99999})\\s|(?<=\\G\\S{0,99999}'.{0,99999}'\\S{0,99999})\\s"
作者: Eric Woodruff 发布者: 2013 年 2 月 21 日

0

16 作者的声誉

一对夫妇对Jan的接受答案进行了有益的调整:

(['"])((?:\\\1|.)+?)\1|([^\s"']+)
  • 允许在带引号的字符串中使用转义引号
  • 避免重复单引号和双引号的模式; 如果需要,这也简化了添加更多引用符号(以另外一个捕获组为代价)
作者: pascals 发布者: 2013 年 3 月 11 日

3

5110 作者的声誉

来自Jan Goyvaerts的正则表达式是我迄今为止找到的最佳解决方案,但也创建了空(空)匹配,他在程序中排除了这些匹配。这些空匹配也来自正则表达式测试人员(例如rubular.com)。如果您转动搜索周围(首先查找引用的部分而不是空格的单词),那么您可以使用以下命令执行以下操作:

("[^"]*"|'[^']*'|[\S]+)+
作者: iRon 发布者: 2013 年 12 月 12 日

1

34036 作者的声誉

Jan的方法很棒,但这是另一个记录。

如果你其实是想分裂在标题中提到,保持引号"will be"'regular expression',那么你可以使用这个方法,是直出的匹配(或替换)的模式,除了在情况S1,S2,S3等

正则表达式:

'[^']*'|\"[^\"]*\"|( )

两个左侧的交替匹配完成'quoted strings'"double-quoted strings"。我们将忽略这些匹配。右侧匹配并捕获第1组的空格,我们知道它们是正确的空格,因为它们与左侧的表达式不匹配。我们用SplitHere那时分开替换那些SplitHere。同样,这是一个真正的分裂案例,你想要"will be",而不是will be

这是一个完整的工作实现(参见在线演示的结果)。

import java.util.*;
import java.io.*;
import java.util.regex.*;
import java.util.List;

class Program {
public static void main (String[] args) throws java.lang.Exception  {

String subject = "This is a string that \"will be\" highlighted when your 'regular expression' matches something.";
Pattern regex = Pattern.compile("\'[^']*'|\"[^\"]*\"|( )");
Matcher m = regex.matcher(subject);
StringBuffer b= new StringBuffer();
while (m.find()) {
    if(m.group(1) != null) m.appendReplacement(b, "SplitHere");
    else m.appendReplacement(b, m.group(0));
}
m.appendTail(b);
String replaced = b.toString();
String[] splits = replaced.split("SplitHere");
for (String split : splits) System.out.println(split);
} // end main
} // end Program
作者: zx81 发布者: 2014 年 5 月 27 日

0

1 作者的声誉

你也可以试试这个:

    String str = "This is a string that \"will be\" highlighted when your 'regular expression' matches something";
    String ss[] = str.split("\"|\'");
    for (int i = 0; i < ss.length; i++) {
        if ((i % 2) == 0) {//even
            String[] part1 = ss[i].split(" ");
            for (String pp1 : part1) {
                System.out.println("" + pp1);
            }
        } else {//odd
            System.out.println("" + ss[i]);
        }
    }
作者: Rakesh Sosa 发布者: 2016 年 9 月 12 日

1

29 作者的声誉

如果您使用的是c#,则可以使用

string input= "This is a string that \"will be\" highlighted when your 'regular expression' matches <something random>";

List<string> list1 = 
                Regex.Matches(input, @"(?<match>\w+)|\""(?<match>[\w\s]*)""|'(?<match>[\w\s]*)'|<(?<match>[\w\s]*)>").Cast<Match>().Select(m => m.Groups["match"].Value).ToList();

foreach(var v in list1)
   Console.WriteLine(v);

我特意添加了“ | <(?[\ w \ s] *)> ”以突出显示您可以指定任何字符串组的字符。(在这种情况下,我使用<>来分组。

输出是:

This
is
a
string
that
will be
highlighted
when
your
regular expression 
matches
something random
作者: Praveen Singh 发布者: 2017 年 11 月 23 日

0

5 作者的声誉

using System.Text.RegularExpressions;
var args = Regex.Matches(command, "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'").Cast<Match>
().Select(iMatch => iMatch.Value.Replace("\"", "").Replace("'", "")).ToArray();
作者: Rudi Jansen van Vuuren 发布者: 2019 年 7 月 22 日
32x32