我已经看到很多正则表达式的答案非常接近我所需要的,但它并不完全存在。问题是我有一个字符串,我需要在一个字符上拆分(例如:space或'='),但我想忽略引号内的任何内容(甚至引号内的引号)。
我能得到的最接近的是this:
" (?=(?:[^"]*"[^"]*")*[^"]*$)"
哪个效果很好,有两个警告:引号中时间不合适的空格会触发错误的分割,并向后读取。我不关心的第一个问题是,我无能为力,我可以解决它。但第二个是至关重要的。
案例是,有时我正在复兴的字符串可能会在最后意外遗漏一句话。这并没有真正打扰我的系统,但上面的正则表达式向后,所以它打破了一切:
string test = "foo bar \"foo bar\" foobar \"foo"
var result = Regex.Split(test, " (?=(?:[^"]*"[^"]*")*[^"]*$)");
这将使:
foo bar "foo
bar" foobar "foo
因为它从最后开始并向后运行过滤器。我需要结果:
foo
bar
"foo bar"
foobar
"foo
我知道$负责最后的事情,但我不能为我的生活弄清楚如何扭转它。想法?
答案 0 :(得分:1)
分割时可以使用此正则表达式。
("[^"]+"|\s+)
如果将模式括在括号内,则大多数拆分函数将返回使用的分隔符。在这种情况下,您首先尝试在当前位置匹配带引号的单词,如果您无法匹配,则选择匹配空格。
获得所有值后,只需删除那些仅包含要丢弃的分隔符的值(在这种情况下为空格)。
以下是使用Perl的示例。
use warnings;
use strict;
my $string = "foo bar \"foo bar\" foobar \"foo";
my @array = grep { ! /^\s*$/ } # Discard matches containing only spaces.
split /("[^"]+"|\s+)/, $string; # Split on whitespace or character withing quotes
# Return delimiters as part of the match.
print "$_\n" foreach @array;
<强>输出强>
foo
bar
"foo bar"
foobar
"foo
答案 1 :(得分:1)
它实际上并不向后运行,只是前瞻必须在每次应用时都一直匹配到最后。这是唯一可以确定在当前位置之后有偶数引号的方式。
但这无论如何都是一个黑客的解决方案;只有当你被迫使用Split()
时才应该做的事情。匹配令牌本身通常要容易得多。例如:
string s = @"foo bar ""foo bar"" foobar ""foo";
Regex r = new Regex(@"[^""\s]+|""[^""]+(?:""|$)");
foreach (Match m in r.Matches(s))
{
Console.WriteLine(m.Value);
}
输出:
foo
bar
"foo bar"
foobar
"foo
编辑:此版本允许不带引号的令牌包含引号:
@"[^""\s]\S+|""[^""]+(?:""|$)"
我仍然假设不带引号的令牌不能包含任何空格。
编辑:似乎引号一直是特殊的,而不仅仅是它们是令牌中的第一个非空白字符。在此版本中,令牌可能以非引号开头或结尾,而可能包含一个或多个带引号的序列。因为所有内容都是可选的,所以它以前瞻开头,以防止它匹配空字符串。
@"(?=\S)[^\s""]*(?:""[^""]+(?:$|""[^\s""]*))*"
和以前一样,最终的收盘价是可选的。
答案 2 :(得分:0)
如果您尝试使用此方法
,该怎么办?string test = "foo bar \"foo bar\" foobar \"foo";
if (test.Count(q => q == '"')%2 == 1)
test += "\"";
test = Regex.Replace(test, "\"[^\"]+\"", "");
测试它是否有奇数引号,如果有,则加一。然后使用"\"[^\"]+\""
删除引号内的任何内容。然后你可以使用String.Split()
答案 3 :(得分:0)
我认为Regex 1或Regex 2应该可以解决问题。
# =====================================
# Regex 1
# =====================================
# ("[^"]")|[\s=]+ // raw
# "(\"[^\"]\")|[\\s=]+" // escped
# @" // verbatim
# (""[^""]"")|[\s=]+
# "
# -------------------------------------
#
# ( " [^"] " ) # expanded Regex 1
# |
# [\s=]+
# =====================================
# Regex 2
# =====================================
# ("(?:[^"]*"[^"]*")*[^"]*")|[\s=]+ // raw
# "(\"(?:[^\"]*\"[^\"]*\")*[^\"]*\")|[\\s=]+" // escaped
# @" // verbatim
# (""(?:[^""]*""[^""]*"")*[^""]*"")|[\s=]+
# "
# -------------------------------------
#
# ( # expanded Regex 2
# "
# (?: [^"]* " [^"]* " )*
# [^"]*
# "
# )
# |
# [\s=]+