问题描述:

I have a large number of files and I want to replace some lines from all of these files. I don't know the exact contents of the lines, all I know is all of them contain two known words - let's say for example 'Programmer' and 'Bob'. So the lines I want to replace could be something like:

Created by Programmer Bob

Programmer extraordinaire Bob, such an awesome guy

Copyright programmer bob, all rights reserved

So far this sounds easy, but the problem is I only want to replace the lines that are contained within a line range - for example in the beginning of the file (where typically one would find comments regarding the file). I can't replace lines found in the later parts of the file, because I don't want to accidentally replace actual code.

So far I have tried:

find . -exec grep -il -E 'Programmer.*Bob' {} \; | xargs sed -i '1,10 /Programmer.*Bob/Ic\LINE REPLACED'

(I'm using find because grep ran into an infinite recursion - I think. Not the point here.)

However it seems that I can't use address ranges with c\ (change line). Feel free to point out any syntax errors, but I think I've tried everything to no avail. This does work without the line numbers.

EDIT:

I got the answer, but I decided to edit my question to include my solution which expands upon the answer I got - maybe someone will find this helpful.

I realised later that I want to retain the possible whitespace and comment characters in the beginning of the line. I accomplished it using this command:

find . -exec grep -ilI '.*Programmer.*Bob.*' {} \; xargs sed -i -r '1,10 s/([ \t#*]*)(.*Programmer.*Bob.*)/\1LINE REPLACED/I'

\1 keeps the pattern that matches [ \t#*]*. One could change this to ^[ \t#*]* that would anchor the pattern to the beginning of the line, but (I THINK) this current version would change

** Text I don't want to remove ** Programmer Bob

into

** Text I don't want to remove ** LINE REPLACED

Which could actually be better. (I also added the -I (capital i) flag to the find command, which skips binary files.)

网友答案:

You are mixing addresses and commands. Simple substitution should work:

find . -exec grep -il -E 'Programmer.*Bob' {} \; \
    | xargs sed -i '1,10 s/.*Programmer.*Bob.*/LINE REPLACED/'
网友答案:
find . -type f -name "*.cpp"|xargs perl -pi -e 'if(/Programmer/ && /Bob/ && $.>=1 && $.<10){$_="line to replace"}'
网友答案:

sed command:

 >sed '1,10 {s/programmer\|bob/LINE REPLACED/i;s/programmer\|bob//ig}' file
相关阅读:
Top