Help with search and replace regex
-
Hello,
I have project in Unity where I want to change some animation parameters via Notepd++. I have too many of them to do it by hand so I tried using regular expressions, but I’m new to it and got stuck. The files I want to edit are Unity .anim files, but it shouldn’t matter.I want to change values “inSlope:” and “outSlope:” to Infinity, but I only want to affect where the next “attribute:” value is m_IsActive. It will be better visible on the example data.
Data before (it is trimmed to save space):
- curve: serializedVersion: 2 m_Curve: - serializedVersion: 3 value: 0 inSlope: 0 outSlope: 0 tangentMode: 0 m_RotationOrder: 4 attribute: m_IsActive - curve: serializedVersion: 2 m_Curve: - serializedVersion: 3 value: 5 inSlope: 0 outSlope: 0 tangentMode: 0 - serializedVersion: 3 value: 1 inSlope: 0 outSlope: 0 tangentMode: 0 - serializedVersion: 3 value: 5 inSlope: 0 outSlope: 0 tangentMode: 0 m_RotationOrder: 4 attribute: m_Frame - curve: serializedVersion: 2 m_Curve: - serializedVersion: 3 value: 1 inSlope: 0 outSlope: 0 tangentMode: 0 m_RotationOrder: 4 attribute: m_IsActive
Data after:
- curve: serializedVersion: 2 m_Curve: - serializedVersion: 3 value: 0 inSlope: Infinity outSlope: Infinity tangentMode: 0 m_RotationOrder: 4 attribute: m_IsActive - curve: serializedVersion: 2 m_Curve: - serializedVersion: 3 value: 5 inSlope: 0 outSlope: 0 tangentMode: 0 - serializedVersion: 3 value: 1 inSlope: 0 outSlope: 0 tangentMode: 0 - serializedVersion: 3 value: 5 inSlope: 0 outSlope: 0 tangentMode: 0 m_RotationOrder: 4 attribute: m_Frame - curve: serializedVersion: 2 m_Curve: - serializedVersion: 3 value: 1 inSlope: Infinity outSlope: Infinity tangentMode: 0 m_RotationOrder: 4 attribute: m_IsActive
The closest expression to select I came up with is:
Find What =(.*inSlope: .\r\n)(.*outSlope: .\r\n)(?=(.|\r\n)*attribute: m_IsActive)
Did not come up with replace expression for it yet.
Search Mode = REGULAR EXPRESSION
Dot Matches Newline = NOT CHECKEDI have tried few of my ideas, but the inSlope and outSlope before attribute: m_Frame are also selected. What I want to is replace every inSlope and outSlope, but only if next attribute is m_IsActive. I have been trying to do it on regex101, here’s my link: https://regex101.com/r/rfaRjW/1
I feel like I am missing something fairly basic here, but I have been stuck on this for few hours already. Thanks for help! -
@Mister-Acer said in Help with search and replace regex:
I feel like I am missing something fairly basic here, but I have been stuck on this for few hours already. Thanks for help!
What you are trying can be difficult. That’s because the regex
will
try to find what is in the lookahead. There is some help at hand. If you look at this post, you might be able to formulate one that suits.I did create one but it relies on there being exactly 2 lines between the “slope” and the m_attribute lines. It would seem from your post that might not always be the case.
Find What:
(?-s)(.+?inSlope: )(.+\R)(.+?outSlope: )(.+\R)(?=.+\R.+\R.+?attribute: m_IsActive)
Replace With:${1}Infinity\r\n${3}Infinity\r\n
However my solution may also help as you can see how I saved different portions of the lines to change into different groups, then only wrote back some of the groups, replacing other portions with the replacement text.
Have a go at using the generic regex I linked to, since it would seem you are somewhat fluent in regex. Come back to our post with more questions if needed.
Terry
-
@Mister-Acer said in Help with search and replace regex:
I feel like I am missing something fairly basic here, but I have been stuck on this for few hours already.
Nope, this is the exact opposite of “very basic”. It’s doable, but complicated.
Thanks for sharing detailed before and after text, as well as the regex you tried.
(.*inSlope: .\r\n)(.*outSlope: .\r\n)(?=(.|\r\n)*attribute: m_IsActive)
At least one problem with this is that, because
. matches newline
is on, and.*
is greedy, the first.*
wants to match from the beginning of the file (or wherever you start your search) and the second.*
wants to match until the very lastoutSlope
that’s followed byattribute: m_IsActive
.With your description, I would be tempted to start by trying the Replacing In a Specific Zone of Text regex that is linked in our Generic RegEx FAQ, using
- FR:
(inSlope|outSlope): .$
- RR:
$1: Infinity
- BSR:
^- curve:
- ESR:
attribute: m_IsActive
… which would say to search for inSlope or outSlope lines between
- curve:
andattribute: m_IsActive
and replace themBut I will admit that I haven’t had a chance to try it out, so there might be some issues with the fact that some
-curve
sections don’t have that same attribute, so I’m not sure if it might select too much.As an alternative:
- FIND =
((?:in|out)Slope): \d(?s)(?=((?!attribute:).)*attribute: m_IsActive*)
and replace withinSlope: Infinity
REPLACE =$1: Infinity
The left puts inSlope or outSlope in group#1, the right says “look ahead to find
attribute: m_IsActive
as long as there aren’t any otherattribute:
lines in between”. The replacement then usesinSlope
oroutSlope
and replaces the digit withInfinity
(if it might be more than one digit, change the
\d
to\d+
. If it might be letters or digits, use\w+
instead)Thanks for a well-asked question. I hope one of these two works for you.
(I see Terry came up with something, too, at about the same time.
- FR:
-
Here’s a variation for some fun:
First, I’d suggest doing
inSlope
andoutSlope
separately; it’s only 2 operations instead of 1 after all…Try (for
inSlope
):Find what:
(?-is)(inSlope: )(\w+)(?s)((?:.*?attribute: )(?:(m_IsActive)|\w+))
Replace with:${1}(?{4}Infinity:${2})${3}
Sure, it can be simplified, probably the most obvious thing would be using lookbehinds and lookaheads to definitely simplify the replace term, but it could be a starting point for experimentation.
-
@PeterJones
Thank you very much for help, I have tried your alternative solution and it did exactly what I wanted! I will also experiment with other solutions later to learn regex better as it was my first time trying something more complex and I see myself using it in the future.I thought it was fairly basic thing but now I understead it was more problematic then that. Well, there’s first time for everything, at least now I have slightly better understaning of the possibilities.
Again, thank you all for help!
-
Hello, @mister-acer, @terry-r, @peterjones @alan-kilborn and All,
I noticed that there is ALWAYS a line
value: \d+
before any lineinSlope: \d+
.Thus, if we consider any
...Slope \d+
line, which is followed, further on, by the nearest lineattribute: m_IsActive
( due to a positive look-ahead ) and where any character, beforeattribute: m_IsActive
, does not begin the stringvalue
( due to a negative look-ahead), we also get a right solution !This description leads to this regex S/R :
SEARCH
(?xs-i) ( inSlope | outSlope) : \x20 \d+ (?= ( (?! value ) . )+? attribute: \x20 m_IsActive )
REPLACE
$1: Infinity
Notes :
-
I use the Free Spacing mode
(?x)
for an easy reading of the search regex -
We also use the Single Line mode
(?s)
as we perform a multi-lines search -
Finally, it’s obvious that we must use the Not Insensitive mode
(?-i)
-
The desired expression is the regex
(inSlope|outSlope): \d+
-
The positive look-ahead is
(?=((?!value).)+?attribute: m_IsActive)
-
The negative look-ahead is
(?!value)
Best Regards
guy038
-
-
It is good that a solution here helped out the OP, but as I read the problem statement, it struck me that, although sample data was provided, perhaps the larger data set doesn’t always conform to the key parts of the sample. Only the OP knows this (or could know it by looking at more of his data set). People proposing solutions wouldn’t know it, so they may “key off” of some things that aren’t true in the larger data set.
I guess my basic point is that OP should really look hard at his data set and make sure that the solution chosen really does what is intended for all of the data set. This is somewhat obvious, but it is easy to “grab and go” with a solution, and then find out later that you haven’t covered all cases, or worse, you’ve irretrievably corrupted your data.
It always seems easier to “trust” someone else’s solution is good for your problem. (Think about “code-grab-and-go” from a stackoverflow solution.) When you’re developing your own solution, you tend to look at things with a closer and more-critical eye.
Of course, if a problem with the data conversion is noticed down the road, OP could come back here and “complain” that the solution was deficient, to be told that the solution was adequate for the sample data and problem description.