GWild
GWild

Reputation: 3

Linux GREP/SED [xargs] find pattern and line number in files and remove with SED

My situation is:

  1. I have a very long text string, containing special characters, which occurs on a long line in various files. Files containing the string are throughout the file system (Linux). The string may be on various line numbers in the files where it occurs, but occurs once per file. The string, however, contains a specific pattern which I can key on for identification of the entire string.

  2. I know how to find the names of files containing the string by keying on the 'prefix' of the string using GREP -lir mystringprefix /path.

  3. I know how to determine the line number of the string in the file using GREP and SED using grep -n "prefix" file.name | sed -n “s/^([0-9])[:]./\1/p”.

  4. I know how to use SED to delete in place the line in the file containing the string of interest using sed -i xd /path/file (x is the line number to be deleted).

My question is how can I put all this together to determine which files contain the pattern, pass the name to GREP to determine the line number in the file, then pass both the name and line number to SED to remove the line?

I need to do this in such a way as to start in a certain location in the filesystem then have it search/delete recursively.

Thank you.

Upvotes: 0

Views: 2961

Answers (2)

komar
komar

Reputation: 881

Pattern is case-sensitive.

grep -Zlr 'mystringprefix' /path/ | xargs -0 sed -i '/mystringprefix/d'

Upvotes: 0

sorpigal
sorpigal

Reputation: 26096

Pretty simple:

for file in "$(grep -lir 'prefix' /path/)" ; do
    sed -ibk -e '/prefix/d' "$file"
done

Where we presume that grep -lir prefix /path/ returns a newline-delimited list of file names and that your prefix pattern is also something sed will understand.

I don't need to determine the line number here because I am telling sed to find lines that match prefix and delete them directly. The for file in "$(grep ...)" construct is somewhat unsafe, however, because an attacker could craft a filename that would cause it to do something you don't expect. It would be better to say:

grep -lir 'prefix' /path/ --null | while IFS= read -r -d '' file ; do
    sed -ibk -e '/prefix/d' "$file"
done

Although note that variables assigned in the body of the while loop will not survive it.

Upvotes: 2

Related Questions