【问题标题】:c# replace expression "except if"c# 替换表达式“除非”
【发布时间】:2018-11-14 05:16:05
【问题描述】:

我正在尝试替换字符串的子字符串,例如

this is some weird text that I want to format text for some ='custom text' content "text" ="text"...

结果应该是

this is some weird sentence that I want to format sentence for some ='custom text' content "sentence" ="text"...

我想用sentence 替换所有出现的text,除非出现在='...'="..." 中。

处理精确引用的事件(即="test"='test')相当容易,但我被包含的部分卡住了......

我想过正则表达式,但我对它们不够熟悉,无法成功......

【问题讨论】:

  • “上下文”怎么样;那应该用“句子”替换“文本”并获得“同意”吗?您正在为严重的缺陷做好准备。考虑编写一个词法分析器。
  • “consentenceual”,听起来像是#metoo 运动中的东西。
  • 我不明白为什么在你的例子中 content "text" 被替换了。你说如果text 用引号括起来,你就不想替换,而且确实如此。
  • text="text='text="text='text 呢?其中有多少被替换了,为什么?您的问题未指定。 你在这里设计一种编程语言,所以要小心
  • @EricLippert 看起来规则是包含在以=为前缀的引号(单引号或双引号)中

标签: c# replace substring


【解决方案1】:
(?<!\=\s*?(\'[^']*)|(\"[^"]*))text

替换为sentence

这是对='(而不是另一个撇号)进行可变长度的负向后查找。与" 相同。基本上,如果它发现它背后的匹配,它将拒绝匹配。

这仍然相对脆弱,可能会被转义的引号或不匹配的引号破坏,但根据您的数据,它可能是可以接受的。它肯定会在人工监督下工作。

如果像Data='Bob said "Mary's not here yet" text' 这样的字符串是一个严重的问题,我会跳过正则表达式方法。

点击这里查看: (Context tab)

【讨论】:

    【解决方案2】:

    我知道它看起来不像,但您正在设计一种语言。实际上是一种非常简单的字符串处理语言。因此,像处理设计编程语言一样处理问题。您的工作流程应该是:

    • 将输入字符串词法化为标记序列
    • 使用您的规则转换标记序列
    • 将标记序列转换回字符串

    第一个比较难,但没那么难。你可以做到的。

    您的词法分析器可以建模为状态机。那就是:

    • 我们跟踪“当前状态”
    • 我们处理每个字符,一次一个
    • 处理仅取决于两件事:它是什么字符,我们处于什么状态?
    • 这会产生两件事:(1) 新的当前状态(可能与旧状态相同)和 (2) 决定是或否,我们是否处于令牌边界?
    • 如果我们在令牌边界上,那么我们将一个新令牌添加到令牌列表中。

    当我们处理完每个字符后,我们就得到了一个标记列表。

    让我们看看您的示例的一些典型词法分析器规则。我们总是从说状态开始:

    • 有四种状态:Normal、Equals、Single 和 Double
    • 我们从正常状态开始

    现在说说在每个州该做什么:

    • 在正常状态下,如果你得到一个=,如果有则结束当前令牌,开始一个新的Equals令牌,添加=,然后进入Equals状态。否则,如果有,则将字符添加到当前令牌中,如果没有,则创建一个新的普通令牌。
    • 在 Equals 状态下,结束当前令牌。如果您收到',请转到单一状态并创建一个单一令牌。如果您收到",请创建一个 Double 令牌并进入 Double 状态。如果您收到=,请创建一个 Equals 令牌并保持 Equals 状态。否则创建一个正常令牌并返回正常状态。将字符添加到当前标记。
    • 在 Single 状态下,将字符添加到当前标记。如果您收到',请转到正常状态。否则,保持 Single 状态。
    • Double 状态也是如此。
    • 如果字符已用完,请结束当前令牌。

    等等。你看这是怎么回事。我们有一个非常简单的小机器,它只是遍历所有字符并决定到目前为止我们所看到的文本类型,以及此时是否将其分解。您最终会得到一个标记列表,其中每个标记都有一部分字符串。

    现在您可以对 Normal 令牌进行搜索和替换,因为您知道您不会对任何 Single、Double 或 Equals 令牌进行替换。

    然后将替换的字符串以相同的顺序重新组合在一起,就完成了。

    【讨论】:

    • 我认为普通标记还需要一个单词边界规则来结束当前/开始下一个普通标记,对吗?否则,我希望借用您的示例,contextual 之类的单词会出现不正确的替换。
    • @JonathonChase:是的,这使问题复杂化了,但它减少了只是普通标记的复杂性。该问题可以在普通标记上解决,或者可以改进词法分析器。关键是引用字符串的问题已经消失了。
    猜你喜欢
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 2011-03-21
    • 2022-06-12
    • 1970-01-01
    相关资源
    最近更新 更多