Community
    • Login

    How to remove text on a specific line across different files

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    7 Posts 4 Posters 442 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.
    • StealthyS
      Stealthy
      last edited by

      Hi there,

      I have a bunch of text files with numbers in them (user data in each file)

      I’m trying to find out how to replace all text on the second line in each file to 0 all at once with the “Replace all in all opened documents” feature

      Any chance anyone knows how to do this?

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

        @Stealthy said in How to remove text on a specific line across different files:

        I’m trying to find out how to replace all text on the second line in each file to 0 all at once with the “Replace all in all opened documents” feature

        Do you mean for every character on the second line you want that character replaced with a 0 (zero)? Or do you mean just 1 0 on that second line? Or do you mean to delete the second line, in which case remove it including the end of line (carriage return/line feed) or just make it an empty line?

        Maybe an example before and after (yes I know it sounds stupid having to do it), but your description is a bit vague.

        Terry

        StealthyS 1 Reply Last reply Reply Quote 0
        • StealthyS
          Stealthy @Terry R
          last edited by

          @Terry-R Hi, sorry for the confusion.

          I mean to replace the whole second line with one singular “0” like this:

          
          31921
          19083
          
          

          to

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

            @Stealthy said in How to remove text on a specific line across different files:

            I mean to replace the whole second line with one singular “0” like this:

            Would something like this suffice then?

            As this is a regular expression, the search mode must be regular expression.
            Find What:(?-s).*\R\K.*(?s)(\R.+)
            Replace With:0${1}

            So it parses the first line, then forgets it (\K). this allows the cursor to start on the second line. It captures that (but does not save it to a group #) and then captures the remainder of the file which is saved to group #1. It then writes a single zero on the second line replacing what it originally captured, then writes back the remainder of the file.

            Terry

            PS I edited the Find What 20 minutes later, so please recheck. Sorry, I had somehow forgotten a crucial piece of the expression when posting

            StealthyS 1 Reply Last reply Reply Quote 3
            • StealthyS
              Stealthy @Terry R
              last edited by

              @Terry-R
              It seems to have worked perfectly, thanks so much for the help!

              1 Reply Last reply Reply Quote 1
              • Mark OlsonM
                Mark Olson
                last edited by Mark Olson

                While it seems that this specific problem has already been adequately solved by others, I thought I’d throw out a more general solution for replacing an arbitrary line with an arbitrary replacement (implemented in Python, how else).

                You could write a regular expression for this general case, but the annoyingness of this regular expression would scale linearly with the number of lines before the line you wanted to replace.

                The below tool can be used as a CLI tool or a PythonScript script.

                Example command line use: python ..\replace_nth_line.py 2 0 -g *.txt *.csv -r

                import glob
                import os
                import re
                
                def replace_nth_line(fname, line_num, replacement):
                    '''replace the line_num^th line (0-indexed) in file fname with replacement'''
                    with open(fname) as f:
                        lines = f.readlines()
                        if line_num >= len(lines):
                            return
                        line1 = lines[0]
                        for sep in ['\r\n', '\r', '\n']:
                            if line1.endswith(sep):
                                lines[line_num] = replacement + sep
                                break
                    with open(fname, 'w') as f:
                        f.write(''.join(lines))
                
                
                def replace_nth_line_in_files(globs, line_num, replacement, dirname, recurse):
                    '''globs: a bunch of filename patterns, e.g. ['*.txt', '*bar*.csv']
                    line_num: the line number to be replaced with replacement in each file
                    replacement: the thing to replace the line with
                    dirname: root dir for all replacements
                    recurse: whether to recursively search in subdirectories of dirname
                    '''
                    for g in globs:
                        if recurse:
                            g = '**/' + g
                        files = glob.iglob(g, root_dir=dirname, recursive=recurse)
                        for fname in files:
                            fname = os.path.join(dirname, fname)
                            replace_nth_line(fname, line_num - 1, replacement)
                    
                    
                class NotepadNotFound(Exception): pass
                
                def plugin_actions():
                    try:
                        from Npp import notepad, editor
                    except:
                        raise NotepadNotFound
                    curdir = os.path.dirname(notepad.getCurrentFilename())
                    user_input = notepad.prompt(
                        'Enter your choices below',
                        'Replace i^th line in files',
                        '\r\n'.join((
                            'line number: 2',
                            'replacement: 0',
                            f'absolute directory path: {curdir}',
                            'filename patterns (separated by \';\'): *.txt',
                            'recursive search? (Y/N): N'))
                    )
                    if not user_input:
                        return
                    choices = [re.split(': ?', line, 1)[1] for line in user_input.split('\r\n')]
                    if len(choices) < 5:
                        print("write your choices after the colons, and don't erase any lines")
                        return
                    line_num, replacement, dirname, globs, recurse = choices
                    if not dirname:
                        notepad.messageBox('Must enter a directory name!', 'Enter a directory!')
                        return
                    if not os.path.exists(dirname):
                        notepad.messageBox(f'Directory {dirname} does not exist', 'Invalid directory')
                        return
                    replace_nth_line_in_files(
                        globs.split(';'),
                        int(line_num),
                        replacement,
                        dirname, 
                        recurse.lower() == 'y'
                    )
                
                try:
                    plugin_actions()
                except NotepadNotFound:
                    import argparse
                    parser = argparse.ArgumentParser()
                    parser.add_argument('line_num', type=int, help='the line number to be replaced with replacement (1-indexed)')
                    parser.add_argument('replacement')
                    parser.add_argument('dirname', nargs='?', default=os.getcwd())
                    parser.add_argument('--globs', '-g', nargs='*', default='*.txt', help='filenames must match these globs to be edited')
                    parser.add_argument('--recurse', '-r', action='store_true')
                    args = parser.parse_args()
                    replace_nth_line_in_files(
                        args.globs,
                        args.line_num,
                        args.replacement,
                        args.dirname,
                        args.recurse
                    )
                
                1 Reply Last reply Reply Quote 2
                • guy038G
                  guy038
                  last edited by

                  Hello, @stealthy, @terry-R and All,

                  @stealthy, a simple solution would be to use the following regex S/R :

                  SEARCH (?-s)\A.*\R\K.*

                  REPLACE 0


                  Now, we can generalize, using the generic regex S/R below, in order to replace the line N, of EACH file, with the RR regex replacement expression :

                  SEARCH (?-s)\A(?:.*\R){N-1}\K.*

                  REPLACE RR

                  Note that, if we want to replace the first line, in EACH file => N - 1 = 0. So, simply use the regex S/R : (?-s)\A.* !

                  Best Regards

                  guy038

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