C#Regex.Split-希望用字符分割字符串,但允许在';和';
我希望通过C#Regex.Split-希望用字符分割字符串,但允许在';和';,c#,regex,C#,Regex,我希望通过/拆分字符串,但也允许'和'之间的任何内容包含拆分字符。从拆分和任何空格中删除'和' 示例/'TEST/:1'/3分为 Test/:1 3 我有一件事很接近: regex.split(test, "/(?=(?:[^']*'[^']*')*[^']*$)" 但是它仍然有”和空格 string[] fields = Regex.Split(Path, "/(?=(?:[^']*'[^']*')*[^']*$)"); 抱歉,我会更清楚它是我自己的路径格式,用于解析类似EDI的文件
/
拆分字符串,但也允许'
和'
之间的任何内容包含拆分字符。从拆分和任何空格中删除'
和'
示例/'TEST/:1'/3
分为
Test/:1
3
regex.split(test, "/(?=(?:[^']*'[^']*')*[^']*$)"
但是它仍然有”
和空格
string[] fields = Regex.Split(Path, "/(?=(?:[^']*'[^']*')*[^']*$)");
抱歉,我会更清楚它是我自己的路径格式,用于解析类似EDI的文件,它的工作原理如下<代码>/位置:行号/Y位置。我只想进入命令行/TEST:4/6=/Location(TEST):LineNumber(4)/YPosition(6)
。但我的问题是,位置是由我的代码计算出来的,可以是第一个分隔符之前的任何内容。它可以是EDI类型文件中常见的日期格式12/03/03
我希望能够使我的命令看起来像这样/'12/03/03':4/6
,这样当位置被我的regex.split分割时,它不包括('and')位置之间的任何内容
有什么帮助吗?不完全清楚您真正想要实现的目标。如果您想解析类似CSV的文件格式,最好使用CSV解析器;如果要操纵文件路径,请使用标准库的路径操纵函数。两者都比简单的正则表达式更适合处理边缘情况 也就是说,你可以做到
MatchCollection allMatchResults = null;
Regex regexObj = new Regex(
@" "" [^""]* "" # either match a (double-)quoted string
| # or
[^/\s]* # a sequence of characters other than / or whitespace",
RegexOptions.IgnorePatternWhitespace);
allMatchResults = regexObj.Matches(subjectString);
这将不会处理带引号字符串中的转义引号,但如果这些引号不在输入中,它应该可以工作
请注意,
“Test/1”/1/2 3/45
将被分为“Test/1”
、1
、2
、3
和45
,因为空格会被删除,因此也可以用作分隔符。您真正想要实现的目标并不完全清楚。如果您想解析类似CSV的文件格式,最好使用CSV解析器;如果要操纵文件路径,请使用标准库的路径操纵函数。两者都比简单的正则表达式更适合处理边缘情况
class Program
{
static void Main(string[] args)
{
string input = "\"\"/one/\"two/threefour\"/five//";
var separator = "/";
var empty = "(?<empty>\\s*)";
var word = string.Format("(?<word>[^{0}]+)", separator);
var quotedWord = "(?<word>[^\\\"]+)";
var token = string.Format("((\"({0}|{1})\")|({0}|{2}))",empty, quotedWord, word);
var pattern = string.Format("({0}/)+({0})", token);
foreach (var capture in Regex.Match(input, pattern).Groups["word"].Captures)
Console.WriteLine(capture);
}
}
也就是说,你可以做到
MatchCollection allMatchResults = null;
Regex regexObj = new Regex(
@" "" [^""]* "" # either match a (double-)quoted string
| # or
[^/\s]* # a sequence of characters other than / or whitespace",
RegexOptions.IgnorePatternWhitespace);
allMatchResults = regexObj.Matches(subjectString);
这将不会处理带引号字符串中的转义引号,但如果这些引号不在输入中,它应该可以工作
请注意,“Test/1”/1/2 3/45
将被分为“Test/1”
、1
、2
、3
和45
,因为空格被删除,因此也可以用作分隔符。类程序
class Program
{
static void Main(string[] args)
{
string input = "\"\"/one/\"two/threefour\"/five//";
var separator = "/";
var empty = "(?<empty>\\s*)";
var word = string.Format("(?<word>[^{0}]+)", separator);
var quotedWord = "(?<word>[^\\\"]+)";
var token = string.Format("((\"({0}|{1})\")|({0}|{2}))",empty, quotedWord, word);
var pattern = string.Format("({0}/)+({0})", token);
foreach (var capture in Regex.Match(input, pattern).Groups["word"].Captures)
Console.WriteLine(capture);
}
}
{
静态void Main(字符串[]参数)
{
字符串输入=“\”\“\”/one/\“two/three-four\”/five/”;
var分隔符=“/”;
var empty=“(?\\s*)”;
var word=string.Format((?[^{0}]+),分隔符);
var quotedWord=“(?[^\\\”]+)”;
var token=string.Format((\”({0}{1})\”)({0}}{2})),空,引号单词,单词);
var pattern=string.Format(“({0}/)+({0})”,token);
foreach(Regex.Match(输入,模式)中的变量捕获。组[“word”]。捕获)
控制台写入线(捕获);
}
}
课程计划
{
静态void Main(字符串[]参数)
{
字符串输入=“\”\“\”/one/\“two/three-four\”/five/”;
var分隔符=“/”;
var empty=“(?\\s*)”;
var word=string.Format((?[^{0}]+),分隔符);
var quotedWord=“(?[^\\\”]+)”;
var token=string.Format((\”({0}{1})\”)({0}}{2})),空,引号单词,单词);
var pattern=string.Format(“({0}/)+({0})”,token);
foreach(Regex.Match(输入,模式)中的变量捕获。组[“word”]。捕获)
控制台写入线(捕获);
}
}
拆分
并不是这类工作的正确工具。如果只使用斜杠进行拆分,那就可以了,但是添加可选引号后,匹配字段比匹配分隔符要容易得多。下面是一个正则表达式,它允许使用单引号或双引号字符串,并将/
、:
和空格作为分隔符:
Regex r1 = new Regex(@"
""(?<FIELD>[^""]*)""
|
'(?<FIELD>[^']*)'
|
(?<FIELD>[^""'/:\s]+)
", RegexOptions.IgnorePatternWhitespace);
string[] source = { @"/TEST:4/6", @"/'12/03/03':4/6" };
foreach (string s in source)
{
foreach (Match m in r1.Matches(s))
{
Console.WriteLine(m.Groups["FIELD"].Value);
}
Console.WriteLine();
}
重复使用字段
组名可以很容易地删除字段中的引号。这里有一种更“语义”的方法,它在一次传递中匹配整个字符串,并使用命名组将字段值归档。我只是将它们插入替换字符串中,但是您可以使用Groups
方法访问它们,就像我在第一个示例中所做的那样
Regex r2 = new Regex(@"
/ \s*
(?:
(?<Q>[""'])(?<LOC>(?:(?!\<Q>).)*)\1
|
(?<LOC>[^""'/:]+)
) \s*
: \s* (?<LINE>\d+) \s*
/ \s* (?<YPOS>\d+)
", RegexOptions.IgnorePatternWhitespace);
foreach (string s in source)
{
Console.WriteLine(r2.Replace(s,
@"Location(${LOC}):LineNumber(${LINE})/YPosition(${YPOS})")
);
Console.WriteLine();
}
此正则表达式不将空格视为分隔符,但它允许在字段值周围填充空格。它还匹配具有相同构造的单引号和双引号字段。在这种情况下,这并不值得付出额外的复杂性,但这是一种值得了解的技术。
Split
并不是这种工作的正确工具。如果只使用斜杠进行拆分,那就可以了,但是添加可选引号后,匹配字段比匹配分隔符要容易得多。下面是一个正则表达式,它允许使用单引号或双引号字符串,并将/
、:
和空格作为分隔符:
Regex r1 = new Regex(@"
""(?<FIELD>[^""]*)""
|
'(?<FIELD>[^']*)'
|
(?<FIELD>[^""'/:\s]+)
", RegexOptions.IgnorePatternWhitespace);
string[] source = { @"/TEST:4/6", @"/'12/03/03':4/6" };
foreach (string s in source)
{
foreach (Match m in r1.Matches(s))
{
Console.WriteLine(m.Groups["FIELD"].Value);
}
Console.WriteLine();
}
重复使用字段
组名可以很容易地删除字段中的引号。这里有一种更“语义”的方法,它在一次传递中匹配整个字符串,并使用命名组将字段值归档。我只是将它们插入替换字符串中,但是您可以使用Groups
方法访问它们,就像我在第一个示例中所做的那样
Regex r2 = new Regex(@"
/ \s*
(?:
(?<Q>[""'])(?<LOC>(?:(?!\<Q>).)*)\1
|
(?<LOC>[^""'/:]+)
) \s*
: \s* (?<LINE>\d+) \s*
/ \s* (?<YPOS>\d+)
", RegexOptions.IgnorePatternWhitespace);
foreach (string s in source)
{
Console.WriteLine(r2.Replace(s,
@"Location(${LOC}):LineNumber(${LINE})/YPosition(${YPOS})")
);
Console.WriteLine();
}
此正则表达式不将空格视为分隔符,但它允许在字段值周围填充空格。它还匹配具有相同构造的单引号和双引号字段。在这种情况下,这并不值得付出额外的复杂性,但这是一种技术