Community
    • Login

    Replace In files based on a condition

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    30 Posts 8 Posters 7.0k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Graham WhiteG
      Graham White
      last edited by

      Hi,

      I want to replace a string in a large number of files only if that file contains another string e.g replace “abc” with “def” only if the file contains “<123>”

      Is there any way of doing this?

      Regards

      Eko palypseE 1 Reply Last reply Reply Quote 1
      • Eko palypseE
        Eko palypse @Graham White
        last edited by

        @Graham-White

        simple answer yes.
        BUT without knowing how such data could look like it is hard to say
        what needs to be done.

        1 Reply Last reply Reply Quote 0
        • Graham WhiteG
          Graham White
          last edited by

          Hi,

          I have a heap of XML files and I want to replace <LockingStrategy val=“I”/> with <LockingStrategy val=“O”/> in all files that also contain TaskType val=“O”/>

          Regards

          Eko palypseE 1 Reply Last reply Reply Quote 1
          • Eko palypseE
            Eko palypse @Graham White
            last edited by Eko palypse

            @Graham-White

            Can you provide such an xml example?
            The reason why I’m asking is to find out whether
            TaskType val=“O”/> is on the same place always or if it
            can be on different places but within the main tag etc…
            Basically, is there some kind of data layout we can rely on.
            like TaskType val=“O”/> is always five lines before or after X
            or within the same main tag but can occur after and before …

            1 Reply Last reply Reply Quote 0
            • PeterJonesP
              PeterJones
              last edited by

              @Eko-palypse :

              My thought would be, based on his description of “file also contains XXX”, to do an search for ( MATCH followed by lookahead(.*XXX) OR lookahead(XXX.*) followed by MATCH ) – but I don’t have the time right now to convert that to a regular expression and verify it works

              Of course, really, this should be written in a scripting language, and run from a command line rather than from inside Notepad++… but we always seem to be willing to jump through the wonderful hoops that regex provide to make the customer happy. :-)

              Eko palypseE 1 Reply Last reply Reply Quote 2
              • Eko palypseE
                Eko palypse @PeterJones
                last edited by

                @PeterJones said:

                but we always seem to be willing to jump through the wonderful hoops that regex provide to make the customer happy. :-)

                I guess this will end in something like this :-)
                But you are right, with a script it would be something like

                for file in directory
                    open(file)
                        if condition in content
                            search_replace
                
                1 Reply Last reply Reply Quote 1
                • Graham WhiteG
                  Graham White
                  last edited by

                  Hi,

                  I don’t have a data layout. The <TaskType… and the <LockingStra…. are between the tag <Task MainProgram=“N”> and </Task> there can be multiple <Task> </Task> groupings in the xml’s. There is no consistency in the number of lines between the tags. Does this help?

                  I can send a you an example of a couple of the files if that helps. Send me your email address if you require these.

                  Regards

                  1 Reply Last reply Reply Quote 0
                  • Terry RT
                    Terry R
                    last edited by

                    @PeterJones , @Eko-palypse @Graham-White
                    I have an idea to do this in 2 steps. The first would be to ‘touch’ each file with a regex that literally writes back everything to the file ONLY if the required text is present in the file (not changing anything), but that allows the datetime stamp of the file to be updated.

                    Then the second step will ONLY work on those files to change the ‘other’ text which must exist as the datetime stamp was updated in the previous step. This allows for the ‘filter’ text to be anywhere in the file, and won’t require any consideration to the lookahead’s possible failure on large files.

                    Terry

                    Eko palypseE 1 Reply Last reply Reply Quote 0
                    • Eko palypseE
                      Eko palypse @Terry R
                      last edited by

                      @Terry-R

                      I understand what you are saying but I don’t know how you want to achieve that.
                      With regex or script or find replace dialog and replace in all opened files?

                      1 Reply Last reply Reply Quote 0
                      • Terry RT
                        Terry R
                        last edited by Terry R

                        Using the ‘Find in Files’ option, I did a test with a small html file that included the text OTHER_2. Another html file did NOT contain this text.
                        My regex was
                        Find What(?s)(.+?)(OTHER_2)(.+?)(.)
                        Replace With:\1\2\3\4

                        I should say that the last '.` was because I was considering another option, this regex could be a bit shorter but I was only testing.
                        I listed the folder and filter as *.html (so it would only interact with 2 files). The one with the text had it’s datetime stamp updated, the other did NOT.

                        Then for the second regex, you could select those ‘updated’ files and drop them onto NPP and use the regex on all open files and then save them all.

                        I think due to the uncertainty of where the 2 texts would be in relation to each other (1 before 2 or 2 before 1) means it makes it complicated to cater for with 1 regex. Together with the lookahead bug I think it’s likely to come unstuck. Maybe 1 regex could do it, but as @PeterJones said “willing to jump through the wonderful hoops that regex”.

                        Sometimes although regex provides lots of power at our fingertips, maybe sometimes simple (and possibly more steps) means the OP can more easily understand it, and more importantly has the ability to ‘update’ it over time.

                        Terry

                        1 Reply Last reply Reply Quote 3
                        • Eko palypseE
                          Eko palypse
                          last edited by

                          ah, I see my approach is slightly different.

                          1. Start a new npp without any files open
                          2. Using also find in files dialog and search for the condition
                          3. right-click in find result window and click open all
                          4. Using find and replace with option Replace All in All Opened Documents
                          5. Done - I hope.
                          Graham WhiteG 1 Reply Last reply Reply Quote 4
                          • Terry RT
                            Terry R
                            last edited by

                            Hey thanks @Eko-palypse
                            I never realised that option existed (yeah I know it was in front on me ALL this time!). I must admit I was somewhat concerned that I was having to ‘touch’ files, although that was tempered by the fact I was ONLY ‘touching’ those that would be later edited anyways.

                            There was an OP a while back that when presented with something like this was adamant they did NOT want the files’ datetime stamp altered unduly.

                            Terry

                            1 Reply Last reply Reply Quote 2
                            • Eko palypseE
                              Eko palypse
                              last edited by

                              What?? They want to change files without changing its timestamp ?
                              Hmm … doesn’t sound healthy … I don’t say they want do bad stuff but
                              resetting timestamp back to what it was … :-)

                              1 Reply Last reply Reply Quote 0
                              • PeterJonesP
                                PeterJones
                                last edited by

                                If you are willing to run the search/replace multiple times, if you have files like

                                <LockingStrategy val="I"/>
                                <SomethingElse/>
                                <LockingStrategy val="I"/>
                                <SomethingElse/>
                                <TaskType val="O"/>
                                <LockingStrategy val="I"/>
                                <SomethingElse/>
                                <LockingStrategy val="I"/>
                                <SomethingElse/>
                                

                                The the following search+replace (Find in Files) will get all the matches before the condition, and at least one of the matches after the condition. However, if there is more than one after the condition, you will have to run the replace in files more than once.

                                With a bit more tweaking, I am sure it could be made to work all in one go, but I haven’t been able to figure it out yet.

                                • Find = (?s)(<LockingStrategy val="I"/>(?=.*TaskType val="O"/>)|(?=TaskType val="O"/>).*\K<LockingStrategy val="I"/>) or (?s)(<LockingStrategy val="I"/>(?=.*TaskType val="O"/>)|(?=TaskType val="O"/>).*?\K<LockingStrategy val="I"/>)
                                  • the first will find the LAST match after the condition as the post-condition to be replaced
                                  • the second will find the FIRST match after the condition as the post-condition to be replaced
                                  • the match-before-condition will find all of them.
                                • Replace = <LockingStrategy val="O"/>
                                • Search Mode = Regular Expression

                                I technically only tried this in one file at a time, but in theory, everything that works in one file will work the same in multiple files. I did verify it worked if there were no matches after the condition, and it “works” (replaces one at a time) if all the matches are after the condition.

                                I’ve got another idea, but not sure if I’ll have time to test it tonight (and will have forgotten it by tomorrow), so I’ll post for now.

                                1 Reply Last reply Reply Quote 2
                                • PeterJonesP
                                  PeterJones
                                  last edited by

                                  Yeah, the second idea isn’t going to work as I had it.

                                  What I am looking for is a way (similar to \K) to reset the beginning of the match back to the beginning of the TaskType val="O"/> after the replacement has occurred, so that it’s searching from that same spot again to find the next match. But I don’t know how to do that.

                                  For now, the best I have is to run the replace-in-files multiple times until they’re all gone. Not ideal, I know, especially if there might be thousands of matches after the conditional. Which is why I’m still an advocate for scripting this, not regexing it.

                                  1 Reply Last reply Reply Quote 1
                                  • guy038G
                                    guy038
                                    last edited by guy038

                                    Hello, @graham-white and All,

                                    To be as accurate as possible, I just think that the best would be to get one or some samples of your XML files, first ;-))

                                    So, if you don’t mind, and if your data are not personal nor confidential, simply attach some examples to your mail to :

                                    See you later,

                                    Best Regards,

                                    guy038

                                    1 Reply Last reply Reply Quote 2
                                    • Graham WhiteG
                                      Graham White @Eko palypse
                                      last edited by

                                      @Eko-palypse I am unsure what you mean in step 2 by “Using also” can you please elaborate

                                      Regards

                                      1 Reply Last reply Reply Quote 1
                                      • EkopalypseE
                                        Ekopalypse
                                        last edited by

                                        Don’t be confused by my new name - verification for my account via google isn’t possible at the moment
                                        so I had to register an account at github. phew …

                                        What I meant is,
                                        You start a npp session without any documents loaded or use an
                                        existing npp session and close all documents.

                                        Then use the standard find in files dialog and search for the condition
                                        As a result of this search you should get a new find result windows.

                                        Within the new result window you can right-click and use Open All.
                                        Now you should have all files open which do have the condition in it.

                                        Last step would be using the normal find/replace dialog and define
                                        your find and replace arguments and use the button Replace All in All Opened Documents

                                        This should result in what you want to have.

                                        Meta ChuhM 1 Reply Last reply Reply Quote 2
                                        • Meta ChuhM
                                          Meta Chuh moderator @Ekopalypse
                                          last edited by Meta Chuh

                                          @Ekopalypse

                                          did the google login symbol disappear as an option when you tried to login again, or was there a problem after clicking on the google g icon ?

                                          if the google login just disappeared as an option: make sure you are logged in at google.com, logoff your git account at this community, disable any adblocker or js-blocker and reload the community login page.

                                          EkopalypseE 1 Reply Last reply Reply Quote 2
                                          • EkopalypseE
                                            Ekopalypse @Meta Chuh
                                            last edited by

                                            @Meta-Chuh

                                            no, the button is still there.
                                            When I tried to log in, I was allowed to
                                            enter the name and the password, after that I was
                                            asked what my cell phone number was, since I could not become verified.
                                            As I couldn’t provide the first possibility nor the second
                                            for my account verification, because initially not specified at all,
                                            I get now with every attempt the hint that google could not verify me.

                                            I even get this as confirmation in my gmail inbox,
                                            where I can log in without any problems.
                                            As a hint I get that someone tried to log on from another computer,
                                            right around the time I’m tried to log on here.

                                            Strange…

                                            Meta ChuhM 1 Reply Last reply Reply Quote 2
                                            • First post
                                              Last post
                                            The Community of users of the Notepad++ text editor.
                                            Powered by NodeBB | Contributors