我正在尝试学习C#,来自Python / PHP背景,我正在尝试将脚本从Python移植到开始。
脚本逐行读取文本文件(大约150K行),应用正则表达式列表直到匹配,获取命名组结果并将值添加为类的属性。
以下是数据的样子(每行以'号'开头是新记录的开头):
No.813177294 09/01/1987 150 Tit.INCAL INDÚSTRIA DE CALÇADOS LTDA (BR/PE) *PARÁGRAFO ÚNICO DO ART. 162 DA LPI. Procurador: ROBERTO C. FREIRE No.901699870 02/06/2009 LD6 *Exigência Formal não respondida, Pedido de Registro de Marca considerado inexistente, de acordo com o Art. 157 da LPI No.830009817 12/12/2008 003 Tit.BIOLAB SANUS FARMACÊUTICA LTDA. (BR/SP) C.N.P.J./C.I.C./NºINPI : 49475833000106 Apres.: Nominativa ; Nat.: De Produto Marca: ENXUG NCL(9) 05 medicamentos para uso humano; preparações farmacêuticas; diuréticos, analgésicos; anestésicos; anti-helmínticos; antibióticos; hormônios para uso medicinal. Procurador: CRUZEIRO/NEWMARC PATENTES E MARCAS LTDA
正则表达式如何:
regexp = {
# No.123456789 13/12/2008 560
# No.123456789 13/12/2008 560
# No.123456789 13/12/2008 560
# No.123456789 560
'number': re.compile(r'No.(?P<Number>[\d]{9}) +((?P<Date>[\d]{2}/[\d]{2}/[\d]{4}) +)?(?P<Code>.*)'),
# NCL(7) 25 no no no no no ; no no no no no no; *nonono no non o nono
# NCL(9) 25 no no no no no ; no no no no no no; *nonono no non o nono
'ncl': re.compile(r'NCL\([\d]{1}\) (?P<Ncl>[\d]{2})( (?P<Especification>.*))?'),
'doc': re.compile(r'C.N.P.J./C.I.C./NºINPI : (?P<Document>.*)'),
'description': re.compile(r'\*(?P<Description>.*)'),
...
}
1)我可以使用相同的概念,在每一行中应用每个Dictionary<string, Regex>
,直到匹配一个?
2)如果我这样做,有办法获得Dictionary<string, string>
个命名组的结果吗? (在这个阶段,我可以将所有内容视为字符串)。
3)如果我认为我有这样的课......
class Record
{
public string Number { get; set; }
public string Date { get; set; }
public string Code { get; set; }
public string Ncl { get; set; }
public string Especification { get; set; }
public string Document { get; set; }
public string Description { get; set; }
}
...有一种方法可以使用命名组的值设置属性吗?
4)我完全忽略了这一点,尝试用动态类型的静态类型语言进行编码?如果是这种情况,我该怎么办?
抱歉这个有点冗长的问题。我真的试着恢复这个: - )
提前致谢。
答案 0 :(得分:3)
1,确定
2.,见例如here
3.,是的,与2相同的基本概念
4.,不,C#足够灵活,允许您通过
移植架构另外考虑将this book作为Python程序员.NET的最佳介绍,反之亦然(我有偏见,曾经是技术编辑并且是作者的朋友,但我认为这是客观上可辩护的; - 。)
答案 1 :(得分:2)
(?<first>group)(?'second'group)
,返回的Match对象将支持这样的命名检索。您可以从此对象构建自己的字典或直接传递Match对象var match = Regex.Match("subject", "regex");
var matchedText = match.Groups("first")
Record Record.Parse(namedValueCollection)
将是一种方法答案 2 :(得分:1)
很抱歉这不是具体的答案,但是你可以使用IronPython将你的脚本转换为在CLR下运行然后再转到C#吗?
答案 3 :(得分:1)
如果你真的想学习C#,你应该只需要参考而不是完整的答案,比如this one (RegEx class),但我相信你也可以通过快速的谷歌搜索找到更多的信息。
答案 4 :(得分:1)
您正在寻找的声音可以做到。当然,您需要查看System.Text.RegularExpressions
,特别是那里的Regex
类型。
另外,我真的很喜欢从文件中读取行的迭代器模式:
public static IEnumerable<string> ReadLines(string path)
{
using(var sr = new StreamReader(path))
{
string line;
while ( (line = sr.ReadLine()) != null)
{
yield return line;
}
}
}
您从该基本代码开始(几乎可以在任何地方重复使用)并使用此方法调用它:
public static IEnumerable<Record> ReadRecords(string path)
{
IEnumerable<Regex> expresssions = new List<Regex>
{
new Regex( @"No.(?P<Number>[\d]{9}) +((?P<Date>[\d]{2}/[\d]{2}/[\d]{4}) +)?(?P<Code>.*)" ),
new Regex( @"NCL\([\d]{1}\) (?P<Ncl>[\d]{2})( (?P<Especification>"),
new Regex( @"C.N.P.J./C.I.C./NºINPI : (?P<Document>.*)")
};
foreach ( MatchCollection matches
in ReadLines(path)
.Select(s => expressions.First(e => e.IsMatch(s)).Matches(s)))
.Where(m => m.Count > 0)
)
{
yield return Record.FromExpressionMatches(matches);
}
}
通过向Record类添加一个接受MatchCollection参数的静态工厂方法来完成它。你在这里看到的一件事就是你希望在完成一条记录之前点击每个表达式一次。这将有点不同。但希望这足以让你真正前进。
答案 5 :(得分:0)
dictionary<string,string> dic_test = new dictionary<string,string>();
dic_test.add(key,value);