【问题标题】:Regex Expression that matches a pattern except for specific matches匹配除特定匹配之外的模式的正则表达式
【发布时间】:2017-07-21 22:18:05
【问题描述】:

我正在尝试使用 RegEx 从 HTML 响应中提取名称。到目前为止,我能够做到这一点,除非我得到的比我需要的要多,我不想匹配特定的字符串,例如“日期”或“今天”。

这是我的正则表达式:

<li class="rcbItem">([^:()]{1,20})<\/li>

这是我运行该模式的 HTML 响应的一部分:

            <div class="rcbSlide" style="z-index:6000;">
                <div id="ctl07_ddInspector_DropDown" class="RadComboBoxDropDown RadComboBoxDropDown_Default " style="float:left;display:none;">
                    <div class="rcbScroll rcbWidth" style="width:100%;">
                        <ul class="rcbList" style="list-style:none;margin:0;padding:0;zoom:1;">
                            <li class="rcbItem">...Default Inspector (if any)</li>
                            <li class="rcbItem">Andy Schene</li>
                            <li class="rcbItem">gilberto hubner</li>
                            <li class="rcbItem">Jim Tinner</li>
                            <li class="rcbItem">Kenneth Donovan</li>
                            <li class="rcbItem">RENTAL REG INSPECTORS</li>
                            <li class="rcbItem">Rob Barker</li>
                            <li class="rcbItem">Robert Costello</li>
                            <li class="rcbItem">Ryan BalFour</li>
                            <li class="rcbItem">Sean Angeley</li>
                            <li class="rcbItem">Krissy King</li>
                        </ul>
                    </div>
                </div>
            </div>
            <input id="ctl07_ddInspector_ClientState" name="ctl07_ddInspector_ClientState" type="hidden" />
        </div>
        <span id="ctl07_lblInspector" class="pnlData"/>
    </td>
</tr>
<tr>
    <td>
        <span id="ctl07_lblSetDefaultLabel" class="pnlLabelLight">Set Default</span>
    </td>
    <td>
        <div id="ctl07_ddSetDefault" class="RadComboBox RadComboBox_Default pnlDD" style="width:175px;">
            <table summary="combobox" border="0" style="border-width:0;border-collapse:collapse;table-layout:fixed;width:100%">
                <tr class="rcbReadOnly">
                    <td class="rcbInputCell rcbInputCellLeft" style="margin-top:-1px;margin-bottom:-1px;width:100%;">
                        <input name="ctl07$ddSetDefault" type="text" class="rcbInput radPreventDecorate" id="ctl07_ddSetDefault_Input" value="Next Day (Default)" style="display: block;" readonly="readonly" />
                    </td>
                    <td class="rcbArrowCell rcbArrowCellRight" style="margin-top:-1px;margin-bottom:-1px;">
                        <a id="ctl07_ddSetDefault_Arrow" style="overflow: hidden;display: block;position: relative;outline: none;">select</a>
                    </td>
                </tr>
            </table>
            <div class="rcbSlide" style="z-index:6000;">
                <div id="ctl07_ddSetDefault_DropDown" class="RadComboBoxDropDown RadComboBoxDropDown_Default " style="float:left;display:none;">
                    <div class="rcbScroll rcbWidth" style="width:100%;">
                        <ul class="rcbList" style="list-style:none;margin:0;padding:0;zoom:1;">
                            <li class="rcbItem">Next Day (Default)</li>
                            <li class="rcbItem">Today</li>
                            <li class="rcbItem">Specified Date</li>
                            <li class="rcbItem">Next Available (Insp Cap)</li>
                            <li class="rcbItem">No Specified Date</li>
                        </ul>
                    </div>
                </div>
            </div>

我知道负前瞻和其他帖子:Regex that matches a pattern and doesn't match specific words。但我不能让它为我工作。以下仍然会带回不需要的匹配项:

<li class="rcbItem">((?!Date$)[^:()]{1,20})<\/li>

【问题讨论】:

  • 为什么不使用正则表达式匹配所有内容,然后在第二步中,在解析后删除不需要的匹配项?你和你似乎只知道什么是名字,什么不是。因此,这就是问题所在……与下拉列表中的其他项目相比,名称是什么。
  • 对我试图避免为这种情况创建特定代码,而是在 VS Web 性能解决方案中为 Webtest 创建了提取规则。这样,我通过了 RegEx,它适用于这种情况,但我可以在同一个 WebTest 中为其他情况重用提取规则。

标签: c# regex regex-negation


【解决方案1】:
  1. 您不需要Date$,因为$ 的意思是“这是字符串的末尾。”
  2. 由于您的示例显示包含“日期”的不需要的字符串出现在 &lt;/li&gt; 之前,因此您希望将否定环视放在那里,而不是更早。
  3. 现在,由于您想向后查找日期,因此您需要向后查找,而不是向前查找。 (在您的?! 中间添加&lt;)

这最终看起来像:

<li class="rcbItem">([^:()]{1,20})(?<!Date)<\/li>

如果您还想删除“今天”条目,则将其设为Today|Date:

<li class="rcbItem">([^:()]{1,20})(?<!Today|Date)<\/li>

P.S.:你真的需要在开头检查所有空格吗?

【讨论】:

  • 谢谢!效果很好。开头的空白是无意的,我试图将这一行格式化为此博客中的代码。
  • 啊,你只需要4个空格,但上面必须有一个空行。
【解决方案2】:

由于“日期”或“今天”的位置不固定, 所以这是我的建议:

string[] filter = {"date","today"};
var result = Regex.Matches(yourhtml,"(?i) <li class=\"rcbItem\">([^:()]{1,20})<\/li>")
.Cast<Match>()
.Where(m=>!filter.Any(f=>m.Groups[1].Value.ToLower().Contains(f)));

【讨论】:

    【解决方案3】:

    您不能使用$,因为它表示整个字符串的结尾。

    试试这个:

    <li class="rcbItem">((?!(.)*(Date|Today))[^:()]{1,20})<\/li>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-13
      相关资源
      最近更新 更多