草庐IT

php - 用于匹配名称和可选值的正则表达式

coder 2024-04-14 原文

我有一个 PHP 应用程序,它与支付处理器接口(interface)以处理信用卡。有时,处理器的后响应失败(例如矩阵中的暂时故障),我们没有收到付款的自动通知。在这些情况下,我们会回退到从始终发送的确认电子邮件中输入数据。我希望我的代码解析出电子邮件的文本以获取数据,这似乎是 preg_match_all 的完美用例。问题是电子邮件的格式不正确:它以 name : value 对出现,但它们都在一行上,而且通常值是空白,这让我很困惑。

我非常擅长正则表达式基础知识(量词、分组、字符类、 anchor 、修饰符),但我真的没有前瞻和反向引用的经验,而且它们是否能提供帮助对我来说一点也不明显。

示例数据可能看起来像这样(同样,所有这些都在一行中,只是为了便于阅读而换行):

bypass_first_page : x_company : x_cust_id : 12345 x_customer_ip : x_customer_tax_id : x_description : 98765 x_duty : x_email_customer : an_example@example.com x_fax : x_footer_email_receipt : x_fp_hash : 747ffeddfe4e106a9c67363ebff996ad x_fp_timestamp : 1525100766 x_invoice_num : R000098765 x_login : MY-LOGIN-ID x_logo_url : x_merchant_email : x_method : x_phone : (416) 555-1212 x_po_num : x_receipt_link_method : GET x_reference_3 : 1234 x_relay_response : TRUE x_relay_url :

我想要这样的输出:

[
    [bypass_first_page] =>
    [x_company] =>
    [x_cust_id] => 12345
    [x_customer_ip] =>
    [x_customer_tax_id] =>
    [x_description] => 98765
    [x_duty] =>
    [x_email_customer] => an_example@example.com
    [x_fax] =>
    [x_footer_email_receipt] =>
    [x_fp_hash] => 747ffeddfe4e106a9c67363ebff996ad
    [x_fp_timestamp] => 1525100766
    [x_invoice_num] => R000098765
    [x_login] => MY-LOGIN-ID
    [x_logo_url] =>
    [x_merchant_email] =>
    [x_method] =>
    [x_phone] => (416) 555-1212
    [x_po_num] =>
    [x_receipt_link_method] => GET
    [x_reference_3] => 1234
    [x_relay_response] => TRUE
    [x_relay_url] =>
]

需要注意的重要事项:

  • 字段名称大部分(但不限于)以 x_ 开头。如果只能找到需要这个的解决方案,它可能是可行的。
  • 字段名有空格。
  • 一些字段名称中包含数字。
  • 可以包含空格(例如电话号码)和下划线(例如电子邮件地址)。
  • 当没有值时,冒号和下一个字段名之间只有一个空格。

我最接近的是:

/([\w\d_]+) ?: ([^:]+)/

但这会产生如下输出:

[
    [bypass_first_page] => x_company
    [x_cust_id] => 12345 x_customer_ip
    [x_customer_tax_id] => x_description
    ...
]

this regex101 link可以看出,这是失败的,因为有些冒号与任何东西都不匹配,并且字段名称最终出现在值中(单独或与实际值连接)。我觉得如果有一个修饰符要求匹配整个字符串,或者以某种方式指示一个匹配项必须从前一个匹配项结束的地方开始的 anchor ,那可以很容易地解决这个问题,但我找不到任何提及任何地方都有这样的事情。可能只是我不知道那个东西叫什么?

最佳答案

我找到的最简单的解决方案(到目前为止)是这样的:

(\w+) : ?(.*?)(?= ?\w+ :|$)

Demo

最后,按照 Allen 的建议在末尾添加 ? 可以使输出更好。

(\w+) : ?(.*?)(?= ?\w+ :|$) ?

输出:

[0] => Array
    (
        [0] => bypass_first_page : 
        [1] => x_company : 
        [2] => x_cust_id : 12345
        [3] => x_customer_ip : 
        [4] => x_customer_tax_id : 
        [5] => x_description : 98765
        [6] => x_duty : 
        [7] => x_email_customer : an_example@example.com
        [8] => x_fax : 
        [9] => x_footer_email_receipt : 
        [10] => x_fp_hash : 747ffeddfe4e106a9c67363ebff996ad
        [11] => x_fp_timestamp : 1525100766
        [12] => x_invoice_num : R000098765
        [13] => x_login : MY-LOGIN-ID
        [14] => x_logo_url : 
        [15] => x_merchant_email : 
        [16] => x_method : 
        [17] => x_phone : (416) 555-1212
        [18] => x_po_num : 
        [19] => x_receipt_link_method : GET
        [20] => x_reference_3 : 1234
        [21] => x_relay_response : TRUE
        [22] => x_relay_url :
    )

[1] => Array
    (
        [0] => bypass_first_page
        [1] => x_company
        [2] => x_cust_id
        [3] => x_customer_ip
        [4] => x_customer_tax_id
        [5] => x_description
        [6] => x_duty
        [7] => x_email_customer
        [8] => x_fax
        [9] => x_footer_email_receipt
        [10] => x_fp_hash
        [11] => x_fp_timestamp
        [12] => x_invoice_num
        [13] => x_login
        [14] => x_logo_url
        [15] => x_merchant_email
        [16] => x_method
        [17] => x_phone
        [18] => x_po_num
        [19] => x_receipt_link_method
        [20] => x_reference_3
        [21] => x_relay_response
        [22] => x_relay_url
    )

[2] => Array
    (
        [0] => 
        [1] => 
        [2] => 12345
        [3] => 
        [4] => 
        [5] => 98765
        [6] => 
        [7] => an_example@example.com
        [8] => 
        [9] => 
        [10] => 747ffeddfe4e106a9c67363ebff996ad
        [11] => 1525100766
        [12] => R000098765
        [13] => MY-LOGIN-ID
        [14] => 
        [15] => 
        [16] => 
        [17] => (416) 555-1212
        [18] => 
        [19] => GET
        [20] => 1234
        [21] => TRUE
        [22] => 
    )

我做了更多测试,认为这应该符合要求。

PS:我想到的第一个解决方案是this :

(?:^| )(\w+) : ?(?!\w+ : )(?:(.*?)(?= \w+ :|$))?

它有点冗长,但可能对您也有帮助。

关于php - 用于匹配名称和可选值的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50110007/

有关php - 用于匹配名称和可选值的正则表达式的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  3. ruby - 匹配未转义的平衡定界符对 - 2

    如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。

  4. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  5. ruby - 匹配大写字母并用后续字母填充,直到一定的字符串长度 - 2

    我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种

  6. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  7. ruby - inverse_of 是否适用于 has_many? - 2

    当我使用has_one时,它​​工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290

  8. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  9. ruby - rbenv 安装 ruby​​ 校验和不匹配 osx - 2

    我已经在mountainlion上成功安装了rbenv和ruby​​build。运行rbenvinstall1.9.3-p392结束于:校验和不匹配:ruby-1.9.3-p392.tar.gz(文件已损坏)预期f689a7b61379f83cbbed3c7077d83859,得到1cfc2ff433dbe80f8ff1a9dba2fd5636它正在下载的文件看起来没问题,如果我使用curl手动下载文件,我会得到同样不正确的校验和。有没有人遇到过这个?他们是如何解决的? 最佳答案 tl:博士;使用浏览器从http://ftp.rub

  10. ruby - 正则表达式将非英文字母匹配为非单词字符 - 2

    @raw_array[i]=~/[\W]/非常简单的正则表达式。当我用一些非拉丁字母(具体来说是俄语)尝试时,条件是错误的。我能用它做什么? 最佳答案 @raw_array[i]=~/[\p{L}]/使用西里尔字符进行测试。引用:http://www.regular-expressions.info/unicode.html#prop 关于ruby-正则表达式将非英文字母匹配为非单词字符,我们在StackOverflow上找到一个类似的问题: https://

随机推荐