问题
I have a directory name "technology" that have multiple sub directories in it and each sub directory have at least one *.txt file.
Every "*.txt" file have one line that starts with word "how_to_repeat" and after that it could have any other string value but it contents will only be at one line.
I am using find to find out files that have "how_to_repeat" values in it as shown below.
find . -name '*.txt' -exec grep -H 'how_to_repeat' {} \; |wc -l
127
Now, My question is how can i update the contents of every "*.txt" file such that it replaces the complete line that starts with "how_to_repeat" word with constant string i.e. "how_to_repeat= Run testing data".
Perl script is working but not for the the full line
perl -p -i -e 's/how_to_repeat /how_to_repeat= Run testing data /' `find ./ -name *.txt`
Wondering how it can replace the full line.
回答1:
To match until the end of the line, you just need to add .*
at the end of the matching expression:
s/how_to_repeat .*/how_to_repeat= Run testing data /
So the whole command, as you confirmed in the comments, becomes:
perl -p -i -e 's/how_to_repeat .*/how_to_repeat= Run testing data /' `find ./ -name *.txt`
回答2:
Given that find
is very basic here you really only need grep
, and a simple line of Perl
grep --include=\*.txt -rlH . -e 'how_to_repeat' | xargs
perl -i.bak -wpe's/how_to_repeat\K.*/= Run testing data/'
The -r
(or -R
) searches the path (.
) recursively, while -l
(--files-with-matches
) returns only file names, as needed here. Apart from --include
there are more options in grep
that allow one to tailor more precisely what files/directories to search or not.
Then xargs
feeds those returned filenames to the Perl program.
If you had more complex criteria for what files to look at then find
could help, of course.
Comments
That
\K
drops all matches before it so we need not replace those; see "Lookaround Assertions" in Extended Patterns in perlre. The rest of the line is then matched by.*
and thus replacedThe
-i
changes the file in-place but.bak
makes it keep a backupIt may be possible to build the filelist with a shell glob alone, and then you can pass it directly to the Perl one-liner since the program will not change files in which the pattern isn't found.
Filtering the file list with
grep
first should be faster but you'll only notice that with many files, in particular if not many of them have the phrase (so not many are processed twice)
The regex in the question isn't working because the rest of the line is never matched, so it indeed doesn't get replaced; it'll work with .*
added to the end of your pattern, like above.
来源:https://stackoverflow.com/questions/57983744/how-to-update-contents-of-a-txt-file-in-multiple-sub-directories