Find and Replace



  • Hello. I was hoping someone may be able to help me with an issue I am having. I have a large text document of code for a CNC machine I am running. I need to make a replacement to some code within the document. I think I can do it with notepad++, but I am not sure how. I will give an example of a few lines, and also what I would like them to look like after…

    ++BEFORE++
    G1 X1.2 Z.300 F0.001
    G2 X0.2063 Z.350 R0.45
    Y0.34 X.5 R.1

    ++AFTER++
    G1 X[#501* 1.2] Z.300 F0.001
    G2 X[#501* 0.2063] Z.350 R0.45
    Y0.34 X[#501* .5] R.1

    As you can see, I need to multiply every X value by the “#501” variable and add brackets to the whole equation. Thanks for any suggestions!



  • Try the following regex.

    Find what: ^(G1 X|G2 X|Y0.34 X)([.-0-9]+)
    Replace with: \1[#501\*\2]

    So Ctrl-H (Replace option), add the two fields as shown above. Select Wrap around and the search mode needs to be “Regular Expression”.

    The replacement works wells in your example, hopefully it does so as well with the rest of the file. Please note I’ve also catered for the possibility of the original number (that will appear behind the *) could be a negative (some coord systems use -ve and +ve coordinate numbers). If not the case here, then you could remove the first “-” in the block [.-0-9].

    Terry



  • Sorry, just noticed a typo. I had it working, but gave you a different version which doesn’t work.

    Correct Find What: (G1 X|G2 X|Y0.34 X)([-\.0-9]+)

    Everything else correct.

    Terry



  • @Terry-R

    I’m not one for “regex golfing”, but maybe this shorter one is clearer to the OP for learning/building upon, however, it does make the matching less restrictive, so depending on the OP’s surrounding data it may not be as good:

    Find what zone: X([0-9.]+)
    Replace with zone: X[#501*\1]
    Search mode: Regular expression

    Here’s an explanation of how it works:

    THE FIND EXPRESSION:

    X([0-9.]+)

    • [Match the character “X” literally (case sensitive)][1] X
    • [Match the regex below and capture its match into backreference number 1][2] ([0-9.]+)
      • [Match a single character present in the list below][3] [0-9.]+
        • [Between one and unlimited times, as many times as possible, giving back as needed (greedy)][4] +
        • [A character in the range between “0” and “9”][3] 0-9
        • [The literal character “.”][1] .

    THE REPLACE EXPRESSION:

    X[#501*\1]

    • [Insert the character string “X[#501*” literally][1] X[#501*
    • [Insert the text that was last matched by capturing group number 1][5] \1
    • [Insert the character “]” literally][1] ]

    Created with RegexBuddy

    [1]: http://www.regular-expressions.info/characters.html
    [2]: http://www.regular-expressions.info/brackets.html
    [3]: http://www.regular-expressions.info/charclass.html
    [4]: http://www.regular-expressions.info/repeat.html
    [5]: http://www.regular-expressions.info/replacebackref.html



  • Wow, thanks guys! I will try out these solutions today. You guys rock!



  • Thanks for reminding me Terry. Yes the X value could just as easily be a negative number. I meant the add that as a possibility. Also, if I only want to match and replace a certain part of as file, can I just select the code I want to change and only change that?



  • @Jeremy-H

    the X value could just as easily be a negative number

    If the number can be negative, then you’d want to adjust my find expression to be X([-0-9.]+) if you are going my route.

    if I only want to match and replace a certain part of as file, can I just select the code I want to change and only change that?

    The Replace tab has an In selection checkbox so you can tick that to limit the replacement to only selected text.



  • Not to nitpick (okay, I am nitpicking), but both @Terry-R and @Scott-Sumner’s regexes would match some pretty strange ones. They are good enough, assuming all data is reasonably valid. But they can match some pretty strange bad data:

    X---        -- not ok, IMO
    X-.-        -- not ok, IMO
    X...1...    -- not ok, IMO
    X1.2.3.4    -- not ok, IMO
    

    Adding some additional tests

    X1          -- ok
    X-1         -- ok
    X1.0        -- ok
    X+1.0       -- ok
    X-1.1       -- ok
    X.1         -- ok or not? 
    X+.1        -- ok or not? 
    X-.1        -- ok or not? 
    X1.         -- ok or not? 
    

    The regex X([-+]?[0-9]+(?:[.](?=[0-9]))?[0-9]*) seems to match all the “ok” except the “ok or not?” rows.
    It’s fully explained by regexr.com/3unfp, but in brief: it finds

    • literal X,
    • then 0 or 1 sign characters (+ or -)
    • then at least one digit,
    • then 0 or 1 decimal points (but only if it has at least one digit)
    • then any remaining digits

    So, right now, mine won’t catch X.1 or X1. (actually, it would match the X1 from X1.)

    • If you want it to capture the X.1 family, change the first [0-9]+ to [0-9]*.
    • If you want it to catch the full X1., then change (?:[.](?=[0-9]))? to the much simpler \.?

    For numerical regular expressions, it’s hard to be perfect: mine matches the X1.2 of X1.2.3.4. It would take some effort to avoid matching that one.



  • @PeterJones

    …nitpicking…

    I view it as we’re just here to kickstart an OP into a solution, not deliver a fully QA’d exact solution…so if an OP doesn’t specifically ask for something, what they get back can and probably should be minimal. :-D



  • I know. I just couldn’t help myself dig into it more on this one.

    Oh, re-reading the original post, I see that X.5 is valid, so need to convert my + to a *. Of course, that opens up the bug that it could conceivably match X with nothing after it, because all the optional items optioned out. :-) I won’t fix it, since the OP seems happy with the simpler ones you both provided.



  • So after testing, it looks like Scott solution worked very well for me. Except for one unforeseen issue. Our control also uses X as an argument. I do not want to change he argument value. I tried to find a common pattern between all arguments vs x values and it looks like every value contains a decimal point and all arguments do not. So I am wondering if we can exclude any match that does not include a decimal?



  • As long as you aren’t worried about X., then a simplified version of mine will work: X(-?[0-9]*\.[0-9]*)

    • 0 or 1 negative sign
    • possible digits
    • required decimal point
    • possible digits

    For more regex details, see the FAQ



  • Thanks, that seems to work just like I need it to. One more request of it is not too much trouble. I would also like to try to change these x values by replacing them with a doubled value. I am not sure how the replace feature handles actual equations though. It seems like it should be pretty simple, I wouldn’t need brackets or anything it would simply be…

    X.7 or X0.7 or X0.7000
    to
    X1.4

    Negative values would need to be doubled as well. Thanks!



  • @Jeremy-H
    Regex does NOT do equations, that is other than replacing 1 string with another string it does not “on the fly” calculate a mathematical result and insert that into the replacement field.
    You’d need to go to either a programming language to achieve this, or firstly look for all the unique instances within the file, then work out a replacement string for each one. A regex could then do the replacement.

    Terry



  • @Jeremy-H

    …replacing them with a doubled value…

    No can do…at least not with the methods thus far discussed. One would have to resort to scripting for that kind of replacement.

    A very similar thing is discussed in the Pythonscript documentation for the editor.rereplace() function, as an example, in this case adding one to each integer match found (very coincidentally also following an X!!):

    def add_1(m):
        return 'Y' + str(number(m.group(1)) + 1)
    
    # replace X followed by numbers by an incremented number
    # e.g.   X56 X39 X999
    #          becomes
    #        Y57 Y40 Y1000
    
    editor.rereplace('X([0-9]+)', add_1);
    


  • Doing math goes beyond the realm of pure regular expressions inside notepad++.

    At this point, you’ve reached the stage of needing a full programming language, preferably one with easy access to regular expressions, like Perl or Python. You could then leverage the regexes we’ve already written to parse the data, and grab out the value into a variable; you could then double it, and put that doubled value back into the data stream. It could be a command-line utility, or if you use PythonScript, you could actually do it live inside Notepad++.

    I know there have been some of these G# X# Y# Z# regex questions in the forums before, and doing math on them sounds vaguely familiar to me. Someone may have written a PythonScript that might help with that. There is a rudimentary search of the forums through the magnifying glass at the top of the page, or use a google advanced search with site:notepad-plus-plus.org/community. Good luck



  • Ok, good to know! Thanks again guys for all the help!


Log in to reply