Question about replacement



  • Good morning!

    I have a question about the find and replace feature in notepad++ . Currently, I am using regex to find the line of code I want and then using $0 to replace it on the next new line. Is there a way to specify what line you want the replacement on?

    For example, I have a line of code that goes
    <g
    <rect
    x=".255" y=“5.2”
    <Id = name1

    I can capture the id=name1 using regex, but I need that line of code to replace up where the <g tag is. Is there an easy/simple way to do this without having to write a program?

    Thanks for the help in advance!



  • @Acme1235 ,

    In general, yes. Use enough regex syntax to match multiple lines, and put the name1 (and maybe other things) in capture group(s), and then do a replacement that puts the text where you want it.

    For the specifics, it’s hard to tell, because of the wonky data you’ve shown (I don’t know whether you just omitted much, or whether the forum corrupted your input, or whether your text really does have all those < without any >; see the suggestions below for asking better questions, so that we know what your data looks like)

    For example, if your text really does look like:

    <g
    <rect
    x=".255" y="5.2"
    <Id = name1
    
    
    <g
    <rect
    x="127" y="314"
    <Id = name2
    

    I might use

    • Find What = (?s-i)(^<g)(.*?<Id = )(\w+)
      • the first token says “. matches newline, match case-sensitive”
      • (^<g) says “find <g at the beginning of the line, and store in group 1”
      • (.*?<Id = ) says “find up to the first <Id = and store in group 2”
      • (\w+) puts the next 1 or more word characters (as many as possible) into group 3
    • Replace With = ${1} name="${3}"${2}${3}
      • group 1, followed by literal name=", put group 3 inside the quotes, then add on groups 2 and 3; so this effectively inserts name="...group3contents..." between the <g and the rest of the match
    • Search Mode = Regular Expression
    • Find Next/Replace or Replace All, as appropriate

    to get

    <g name="name1"
    <rect
    x=".255" y="5.2"
    <Id = name1
    
    
    <g name="name2"
    <rect
    x="127" y="314"
    <Id = name2
    

    Since your text probably looks different, you may have to tweak that somewhat, but the idea is there. If you need more help, follow the suggestions below for presenting your before and after text similar to the way I did, and show what regex you tried (if it was different from mine) and what you thought each piece was doing.

    (With regex, there’s almost always many ways of getting the same result. Another idea I had was to just capture the <g line, and use a long positive lookahead assertion to find the nearest Id = name1 and put the name1 in a capture group inside the lookahead. That makes the FIND more complicated, but the REPLACE easier to read. You (or anyone interested) could take it as a homework assignment to read the linked regex docs and see if you can find an equivalent solution to mine, but that uses a capture group inside the lookahead as I described here)

    ----

    Do you want regex search/replace help? Then please be patient and polite, show some effort, and be willing to learn; answer questions and requests for clarification that are made of you. All example text should be marked as literal text using the </> toolbar button or manual Markdown syntax. To make regex in red (and so they keep their special characters like *), use backticks, like `^.*?blah.*?\z`. Screenshots can be pasted from the clipboard to your post using Ctrl+V to show graphical items, but any text should be included as literal text in your post so we can easily copy/paste your data. Show the data you have and the text you want to get from that data; include examples of things that should match and be transformed, and things that don’t match and should be left alone; show edge cases and make sure you examples are as varied as your real data. Show the regex you already tried, and why you thought it should work; tell us what’s wrong with what you do get. Read the official NPP Searching / Regex docs and the forum’s Regular Expression FAQ. If you follow these guidelines, you’re much more likely to get helpful replies that solve your problem in the shortest number of tries.



  • So I actually ended up coding it a little bit easier in xml so I didn’t have to search ahead for a lot of lines. This is the code I have.

    <g
    id="1">
    .......
    </g>
    

    The code I want returned is as follows:

    <g
    idname="1" trueid="001" >
    .......
    </g>
    
    

    This is the regex code I have tried:
    Find :

    (?s)(<g)(.*?id=)

    This code matches new line, puts the <g in a capture group, reads up until it reaches id= and stores the rest of the line in another capture group.
    Replace:

    $1 idname=$3 trueid=00$3

    From what I understand, this creates a new line, and uses capture group 3 to fill out the spots. But it doesn’t work like that.

    This ends up returning:

    <g idname=  trueid=00"1"
    

    The two problems I’m having now is that it’s taking the quotations with the original capture group which makes it hard for the trueid statement. Also, I’m having trouble because it only seems to want to use one $3 in the replace statement.

    Again thanks for all the help! I’m trying to learn regex and hope this shows some effort.



  • @Acme1235 ,

    (?s)(<g)(.*?id=)

    This FIND expression that you showed doesn’t have a group 3:

    (?s)(<g)(.*?id=)
    ^^^^ = not a group, this is an unnumbered option
        ^^^^ = group 1
            ^^^^^^^^ = group 2
    

    … so there’s nothing to insert for $3.

    In your text, <g goes into group 1, \r\nid= goes into group 2, and the rest of the text isn’t part of the match. Then in your replacement, $1 is the <g, $3 is the empty string, so it replaces the text <g\r\nid= with <g idname= trueid=00; since the "1" was next n the string, that’s what comes next after the replacement – it is not the value of the $3.

    With this modified requirement, I would change tactics: don’t include the id= inside any group (since you don’t want to keep that syntax), and put the second group inside the quotes, so it just grabs the single-digit number.

    • FIND = (?s)(<g.*?)\s*id="(\d)"
    • REPLACE = $1 idname="$2" trueid="00$2"

    input =>

    <g
    id="1">
    .......
    </g>
    

    REPLACE ALL output =>

    <g idname="1" trueid="001">
    .......
    </g>
    


  • So if I understand the code correctly, you captured the (<g) and then started scrolling through characters.

    \s denotes a new line.

    The * makes it look for the id=

    And then the \d denotes a digit.

    Thanks again for the help! You’ve been a lifesaver.



  • @Acme1235 said in Question about replacement:

    So if I understand the code correctly, you captured the (<g) and then started scrolling through characters.

    technically, captured the <g, and characters necessary after that to make the whole match work

    \s denotes a new line.

    \s* denotes 0 or more of any whitespace (space, tab, newline)

    The * makes it look for the id=

    The * was the 0-or-more quantifier for the \s

    the id=" makes it look for id="

    And then the \d denotes a digit.

    Yep.

    Thanks again for the help! You’ve been a lifesaver.


Log in to reply