How to remove text on a specific line across different files
-
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?
-
@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 10
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
-
@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
-
@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
-
@Terry-R
It seems to have worked perfectly, thanks so much for the help! -
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 )
-
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 theRR
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