C#解析字符串

5

我有一堆看起来像这样的字符串:

mc_gross=22.99invoice=ff1ca57d9fa80cf93e6b300dd7f063e1protection_eligibility=Ineligibleaddress_status=confirmedpayer_id=SGA8X3TX9HCVYtax=0.00address_street=155 5th ave sepayment_date=16:08:28 Nov 15, 2010 PSTpayment_status=Completedcharset=windows-1252address_zip=98045first_name=jackobmc_fee=1.08address_country_code=USaddress_name=john martinnotify_version=3.0custom=ff1ca5asdf7d9fa80cf93e6b300dd7f063e1payer_status=unverifiedbusiness=gold-me@hotmail.comaddress_country=United Statesaddress_city=north bendquantity=1verify_sign=AZussRXZRkuk7frhfirfxxTkj0BDJGA2dJF3eF263eEsjLixS.xRxCzfaYLpayer_email=me@gmail.comtxn_id=4DU53818WJ271531Mpayment_type=instantlast_name=Martinaddress_state=WAreceiver_email=cravbill@hotmail.compayment_fee=1.08receiver_id=QG8JPB4RZJGG4txn_type=web_acceptitem_name=Some item of consequenceSpecifiemc_currency=USDitem_number=G10W151residence_country=UShandling_amount=0.00transaction_subject=ff1ca57d9fad80cf93e6b300dd7f063e1payment_gross=22.99shipping=0.00

最好的解析方法是什么?你会认为创建它的人会放一些断点......

无论如何,任何帮助都将不胜感激。

编辑:

感谢大家的回复。我想知道是否可以这样做:

  1. 创建标签列表。例如 mc_gross=first_name=,...
  2. 在字符串中进行替换:thestring.replace("first_name","\r\nfirst_name") 我想这将给我需要进一步解析的断点。

你觉得呢?


1
哇,他们当时在想什么啊? - BoltClock
2
请与创建此内容的人核实一下,肯定有些问题。你确定每个键值对之间没有换行符吗? - Chris Taylor
3
这是一组名称/值对的列表,但是在这些对之间没有任何分隔符?你可以回到给你这个列表的人那里问一下:1)他们能否加入一个分隔符,2)当他们创建这个列表时吸了些什么东西。 - DXM
3
哇,要解析这个内容可不是一件简单的任务。你需要去找出是谁写的,然后开始打破沉默。 - ChaosPandion
这个字符串是否是支付网关机制的结果?如果是,他们的网站上可能会有一些帮助来解析它,或者其他消费者如何解析这些信息。 - balalakshmi
显示剩余3条评论
4个回答

3
除非这是固定宽度的(高度怀疑),否则我会说你需要获取指示字段的关键字列表。将它们放入数据库(SQL、XML、CSV等 - 不管在哪里)中,然后使用它们来解析文件。希望这些标签按照相同的顺序出现,并且不会遗漏任何标签。如果是这样,请使用 Substring 找到等号后面的值,该值对应于适当的标签,直到下一个标签的开头。例如,如果我们只考虑第一部分 mc_gross=22.99invoice=ff1ca57d9fa80cf93e6b300dd7f063e1protection_eligibility=Ineligibleaddress_status=confirmed,那么我们的标签将是mc_gross, invoice, protection_eligibility 和 address_status。然后,我们从mc_gross=开始,在字符串中使用 Substring 找到它。为了确定长度,我们会一直找到下一个标签invoice。Substring 的代码行可能比较复杂,但应该能够完成任务。循环处理每个标签。当您到达最后一个标签时,您需要找到字符串的结尾而不是另一个标签。

这就是给了我将断点插入字符串的想法,不确定它是否有效。 - ErocM
这给了我一个很好的开端,我能够将其分成单独的行,然后在“=”上拆分。谢谢! - ErocM

3

正如其他人所述,除非您可以在适当的位置包括换行符的原始数据,否则下一个最好的方法是获取关键名称列表。

我假设其他60K行具有与您提供的示例行相同的关键名称?如果是这样,如果没有人能够提供给您该列表,则手动(而不是编程方式)识别关键名称似乎是唯一的方法。

我自己尝试过。做起来并不太难(最多几分钟),但可能仍然需要有知识的人确认关键字列表是否正确。

一旦您获得了列表,那么您就可以通过关键字进行分割,然后将它们重新组合成一个新列表:

string rawData =
    "mc_gross=22.99invoice=ff1ca57d9fa80cf93e6b300dd7f063e1protection_eligibility=Ineligibleaddress_status=confirmedpayer_id=SGA8X3TX9HCVYtax=0.00address_street=155 5th ave sepayment_date=16:08:28 Nov 15, 2010 PSTpayment_status=Completedcharset=windows-1252address_zip=98045first_name=jackobmc_fee=1.08address_country_code=USaddress_name=john martinnotify_version=3.0custom=ff1ca5asdf7d9fa80cf93e6b300dd7f063e1payer_status=unverifiedbusiness=gold-me@hotmail.comaddress_country=United Statesaddress_city=north bendquantity=1verify_sign=AZussRXZRkuk7frhfirfxxTkj0BDJGA2dJF3eF263eEsjLixS.xRxCzfaYLpayer_email=me@gmail.comtxn_id=4DU53818WJ271531Mpayment_type=instantlast_name=Martinaddress_state=WAreceiver_email=cravbill@hotmail.compayment_fee=1.08receiver_id=QG8JPB4RZJGG4txn_type=web_acceptitem_name=Some item of consequenceSpecifiemc_currency=USDitem_number=G10W151residence_country=UShandling_amount=0.00transaction_subject=ff1ca57d9fad80cf93e6b300dd7f063e1payment_gross=22.99shipping=0.00";

string[] keys = {
                    "mc_gross", "invoice", "protection_eligibility", "address_status", "payer_id", "tax",
                    "address_street", "payment_date", "payment_status", "charset", "address_zip",
                    "first_name", "mc_fee", "address_country_code", "address_name", "notify_version",
                    "custom", "payer_status", "business", "address_country", "address_city", "quantity",
                    "verify_sign", "payer_email", "txn_id", "payment_type", "last_name", "address_state",
                    "receiver_email", "payment_fee", "receiver_id", "txn_type", "item_name",
                    "mc_currency", "item_number", "residence_country", "handling_amount",
                    "transaction_subject", "payment_gross", "shipping"
                };

string[] values = rawData.Split(keys, StringSplitOptions.RemoveEmptyEntries);

IEnumerable<string> parsedList = keys.Zip(values, (key, value) => key + value);

foreach (string item in parsedList)
{
    Console.WriteLine(item);
}

这将以以下格式输出数据:
mc_gross=22.99
invoice=ff1ca57d9fa80cf93e6b300dd7f063e1
protection_eligibility=Ineligible
address_status=confirmed
payer_id=SGA8X3TX9HCVY
tax=0.00
address_street=155 5th ave se
payment_date=16:08:28 Nov 15, 2010 PST
payment_status=Completed
charset=windows-1252
address_zip=98045
first_name=jackob
mc_fee=1.08
address_country_code=US
address_name=john martin
notify_version=3.0
custom=ff1ca5asdf7d9fa80cf93e6b300dd7f063e1
payer_status=unverified
business=gold-me@hotmail.com
address_country=United States
address_city=north bend
quantity=1
verify_sign=AZussRXZRkuk7frhfirfxxTkj0BDJGA2dJF3eF263eEsjLixS.xRxCzfaYL
payer_email=me@gmail.com
txn_id=4DU53818WJ271531M
payment_type=instant
last_name=Martin
address_state=WA
receiver_email=cravbill@hotmail.com
payment_fee=1.08
receiver_id=QG8JPB4RZJGG4
txn_type=web_accept
item_name=Some item of consequenceSpecifie
mc_currency=USD
item_number=G10W151
residence_country=US
handling_amount=0.00
transaction_subject=ff1ca57d9fad80cf93e6b300dd7f063e1
payment_gross=22.99
shipping=0.00    

您可以通过将每个项目按等号(“=”)拆分或用包含缺失换行符的新数据字符串替换原始数据字符串来进一步解析列表:

string newData = parsedList.Aggregate((data, next) => data + Environment.NewLine + next);

1
你做的和我一样的概念,但是你的更优雅。谢谢你的提示! - ErocM

2

建议使用System.Text.RegularExpressions,它们非常有用。

但是,一个简单的方法是使用字符串类中的拆分函数。

string head = "mc_gross=22.99invoice=ff1ca57d9fa80cf93e6b300dd7f063e1protection_eligibility=Ineligibleaddress_status=confirmedpayer_id=SGA8X3TX9HCVYtax=0.00address_street=155 5th ave sepayment_date=16:08:28 Nov 15, 2010 PSTpayment_status=Completedcharset=windows-1252address_zip=98045first_name=jackobmc_fee=1.08address_country_code=USaddress_name=john martinnotify_version=3.0custom=ff1ca5asdf7d9fa80cf93e6b300dd7f063e1payer_status=unverifiedbusiness=gold-me@hotmail.comaddress_country=United Statesaddress_city=north bendquantity=1verify_sign=AZussRXZRkuk7frhfirfxxTkj0BDJGA2dJF3eF263eEsjLixS.xRxCzfaYLpayer_email=me@gmail.comtxn_id=4DU53818WJ271531Mpayment_type=instantlast_name=Martinaddress_state=WAreceiver_email=cravbill@hotmail.compayment_fee=1.08receiver_id=QG8JPB4RZJGG4txn_type=web_acceptitem_name=Some item of consequenceSpecifiemc_currency=USDitem_number=G10W151residence_country=UShandling_amount=0.00transaction_subject=ff1ca57d9fad80cf93e6b300dd7f063e1payment_gross=22.99shipping=0.00";

string splitStrings[] = new string[2];
splitString[0] = "mc_gross";
splitString[1] = "invoice";
string headArray[] = head.Split(splitStrings, StringSplitOptions.RemoveEmptyEntries);

你懂的,它将所有东西都分成了部分。

3
但是如果字符串没有明确定义的模式,那么就没有用了。 - Jeff Mercado

-1

等号是一个非常好的指示器。在等号之间,我建议使用一些带有类型推断引擎的词汇工具。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接