0

I have the following use case. I need a Regex pattern to only match a line, if part of the string does not contain a different string. Here is an example:

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

So here I want to match android:layout_marginStart="12dp" so that I can replace with:

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

I have worked this one out and I can use the following regex to do it:

Find: (.*)android:layout_marginStart="(.*)" Replace: $1android:layout_marginStart="$2"\n$1android:layout_marginLeft="$2"

What I can't do is conditionally match. I do not want to match if this xml object already contains the android:layout_marginLeft attribute.

3

1 Answer 1

1

In regex, if you want to check to make sure a string is not coming up after the part you wish to match, you can use a negative lookahead.

In this example, you want to match something, but only if the string layout_marginLeft is not coming up later. You can do that, but throwing layout_marginLeft into a negative lookahead, like this:

(?:(?!layout_marginLeft).)*

Now, when you combine that with what you actually want to match your regex would look something like this:

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

And then your replacement string would look like this:

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

So, the replacement stuff works the same way, it's just that you are telling it not to do a replacement on anything that already contains layout_marginLeft.

Here is a demo

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for you answer. Very useful. Is there a way to check both after and before? So not to match: android:layout_marginLeft="10dp" android:layout_marginRight="10dp"
Here you go, brother. Notice that I added the single-line s flag to scan across multiple lines. This also meant that I had to change the . in "(.*?)" to not include spaces. "([^\s]*?)". Finally, I added the same negative lookahead to the front of the expression. So now it is in two places.
Massive thank you for taking the time to fix and explain it. I would never have reached this on my own.
Sorry, not done yet. When using in Java I get an issue with the \K character as it's not supported. Not sure how to resolve. People mention about using capturing groups but can't get these to work.
are you able to help with the last piece of the puzzle?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.