Kirs Kringle
Kirs Kringle

Reputation: 929

Matching some lines and deleting them with Perl

Problem:

Many files name.CFG with some bad lines in them (roughly 2700 files). I need to remove the bad lines if they exist.

The bad lines contain the name of the file minus the .CFG

The Bad Lines:

Title[nameofdevice:cpu]: nameofdevice CPU Usage Mhz
Target[nameofdevice:cpu]:
MaxBytes[nameofdevice:cpu]: 100
Options[nameofdevice:cpu]: gauge
WithPeak[nameofdevice:cpu]: wmy
YLegend[nameofdevice:cpu]: Percent
ShortLegend[nameofdevice:cpu]: %
Legend1[nameofdevice:cpu]: CPU % for 1
Legend2[nameofdevice:cpu]: CPU Max for 2
Legend3[nameofdevice:cpu]: Max CPU Mhz for 1
Legend4[nameofdevice:cpu]: Max CPU Mhz for 2

Title[nameofdevice:mem]: nameofdevice mem
Target[nameofdevice:mem]:
MaxBytes[nameofdevice:mem]: 100
Options[nameofdevice:mem]: gauge
WithPeak[nameofdevice:mem]: wmy
YLegend[nameofdevice:mem]: Percent
ShortLegend[nameofdevice:mem]: %
Legend1[nameofdevice:mem]: % Used
Legend2[nameofdevice:mem]: Max Used
Legend3[nameofdevice:mem]: Max

nameofdevice is the name of the file minus the .CFG

I was looking for a linux way to do this, but it seems as though Perl would be more flexible. My real issue is matching the text exactly. I guess having the multiple lines and variable are what is perplexing to me, but a small string you could do a find and replace kind of thing. Or use SED.

I need to remove the bad lines from all of the files.

Upvotes: 2

Views: 97

Answers (3)

JJoao
JJoao

Reputation: 5347

perl -i.bak -ne '$n=$ARGV=~s/\.cfg$//r; print unless /\b$n\b/' *.cfg

or even

... print unless /\b\Q$n\E\b/

It will create a backup (file.cfg.bak)

Upvotes: 1

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51330

This will do the trick (although I believe there's a more efficient way to do this):

find -iname '*.cfg' -execdir perl -i -ne '$f = $ARGV =~ s#\./|\.cfg##gr; print if !m/\b\Q$f\E\b/;' {} \+

If you're on windows, you need to provide a backup file name for the inplace (-i) feature:

find -iname '*.cfg' -execdir perl -ibak -ne '$f = $ARGV =~ s#\./|\.cfg##gr; print if !m/\b\Q$f\E\b/;' {} \+ && find -iname '*.cfgbak' -delete

find -iname '*.cfg' finds every .cfg file in the current directory and all subdirectories.

The Perl script is:

# there's an implied while(<>) because of the -n option
# which executes this script for each line

# $ARGV is the current file path, strip ./ and .cfg
$f = $ARGV =~ s#\./|\.cfg##gr;

# print the current line if it doesn't contain the current file name
# as a whole word
print if !m/\b\Q$f\E\b/;

Upvotes: 2

anubhava
anubhava

Reputation: 784958

Using grep -P (PCRE):

grep -P 'nameofdevice(?!\.CFG)' file

To skip these lines:

grep -v -P 'nameofdevice(?!\.CFG)' file > tmpFile
mv tmpFIle file

Upvotes: 1

Related Questions