How to update contents of a “*.txt” file in multiple sub directories

[亡魂溺海] 提交于 2020-02-23 03:57:09

问题


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 replaced

  • The -i changes the file in-place but .bak makes it keep a backup

  • It 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!