【问题标题】:Only Match String if Text Does Not Contain Another String仅当文本不包含另一个字符串时才匹配字符串
【发布时间】:2019-03-27 00:56:49
【问题描述】:

我有以下用例。如果字符串的一部分不包含不同的字符串,我需要一个正则表达式模式来匹配一行。这是一个例子:

<androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="12dp"/>

所以我想在这里匹配android:layout_marginStart="12dp",以便我可以替换为:

android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"

我已经解决了这个问题,我可以使用以下正则表达式来做到这一点:

查找:(.*)android:layout_marginStart="(.*)" 替换:$1android:layout_marginStart="$2"\n$1android:layout_marginLeft="$2"

我不能做的是有条件地匹配。如果这个 xml 对象已经包含 android:layout_marginLeft 属性,我不想匹配。

【问题讨论】:

标签: regex


【解决方案1】:

在正则表达式中,如果您想检查以确保字符串没有出现在您希望匹配的部分之后,您可以使用否定前瞻。

在这个例子中,你想匹配一些东西,但前提是字符串layout_marginLeft 稍后没有出现。您可以这样做,但将 layout_marginLeft 投入到否定的前瞻中,如下所示:

(?:(?!layout_marginLeft).)*

现在,当你将它与你真正想要匹配的正则表达式结合起来时,你的正则表达式看起来像这样:

(android:layout_marginStart="(.*?)")(?:(?!layout_marginLeft).)*(?=/>)

然后您的替换字符串将如下所示:

\1\n\t\tandroid:layout_marginLeft="\2"

因此,替换内容的工作方式相同,只是您告诉它不要对已包含 layout_marginLeft 的任何内容进行替换。

Here is a demo

【讨论】:

  • 感谢您的回答。很有用。有没有办法同时检查前后?所以不匹配:android:layout_marginLeft="10dp" android:layout_marginRight="10dp"
  • Here you go, brother。请注意,我添加了单行 s 标志来扫描多行。这也意味着我必须将"(.*?)" 中的. 更改为不包含空格。 "([^\s]*?)"。最后,我在表达式的前面添加了相同的否定前瞻。所以现在它在两个地方。
  • 非常感谢您花时间修复和解释它。我自己永远也达不到这一点。
  • 抱歉,还没完成。在 Java 中使用时,我遇到了 \K 字符的问题,因为它不受支持。不知道如何解决。人们提到使用捕获组,但无法使它们发挥作用。
  • 你能帮忙解决最后一块拼图吗?
猜你喜欢
  • 1970-01-01
  • 2017-08-09
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-11
  • 2011-09-27
相关资源
最近更新 更多