jon
jon

Reputation: 953

How can I delete a line in file if the line matched the required PATH, in Perl?

My target is to delete line in file only if PATH match the PATH in the file

For example, I need to delete all lines that have /etc/sysconfig PATH from /tmp/file file

 more /tmp/file

 /etc/sysconfig/network-scripts/ifcfg-lo   file1
 /etc/sysconfig/network-scripts/ifcfg-lo   file2
 /etc/sysconfig/network-scripts/ifcfg-lo   file3

I write the following Perl code (the perl code integrated in my bash script) in order to delete lines that have "/etc/sysconfig"

   export FILE=/etc/sysconfig

   perl -i -pe 's/\Q$ENV{FILE}\E// '   /tmp/file 

But I get the following after I run the perl code: (in place to get empty lines)

  /network-scripts/ifcfg-lo file1
  /network-scripts/ifcfg-lo file2
  /network-scripts/ifcfg-lo file3

first question:

How to change the perl syntax : perl -i -pe 's/\Q$ENV{FILE }\E// ' in order to delete line that matches the required PATH (/etc/sysconfig)?

second question:

The same as the first question but line will deleted only if PATH match the first field in the file

Example:

/tmp/file before perl edit:

   file1 /etc/sysconfig/network-scripts/ifcfg-lo   
   /etc/sysconfig/network-scripts/ifcfg-lo   file2
   /etc/sysconfig/network-scripts/ifcfg-lo   file3

/tmp/file after perl edit:

   file1 /etc/sysconfig/network-scripts/ifcfg-lo   

Upvotes: 1

Views: 1233

Answers (4)

brian d foy
brian d foy

Reputation: 132822

If I were doing this from the command line, I probably wouldn't even use Perl. I'd just use a negated grep:

$ mv old.txt old.bak; grep -v $FILE old.bak > old.txt

Renaming the original file and writing to a new file with the old name is the same thing that perl's -i switch does for you.

If you want to match just the first column, then I might punt to perl so I don't have to use awk or cut. perl's -a switch splits the line on whitespace and puts the results in @F:

 $  perl -ai.bak -ne 'print if $F[0] !~ /^\Q$ENV{FILE}/' old.txt

When you think you have it right, you can remove the .bak training wheels that saves a copy of your original file. Or not. I tend to like the safety net.

See perlrun for the details of command-line switches.

Upvotes: 0

mef
mef

Reputation: 1

mef@iwlappy:~$ cat /tmp/file

aaaa 
/etc/sysconfig/network-scripts/ifcfg-lofile1 
/etc/sysconfig/network-scripts/ifcfg-lofile2 
/etc/sysconfig/network-scripts/ifcfg-lofile3 
aaa 

mef@iwlappy:~$ perl -i -pe 's/$ENV{FILE}\E.*//' /tmp/file

mef@iwlappy:~$ cat /tmp/file 
aaaa
aaa

You can do a further regexp to remove empty lines with s/^$//

Upvotes: 0

Ether
Ether

Reputation: 53976

s/pattern/otherpattern/ won't delete entire lines; it will only alter substrings. You need to entirely change your program to delete entire lines. In pseudocode, it would be:

while (read in a line)
{
    if (doesn't match)
    {
         write the line back out unaltered.
    }
}

It can still be rewritten as a oneliner though, with knowledge of how continue and redo work in loops: perl -pe '$_ = <> and redo if /Q$ENV{FILE}\E/'

Upvotes: 0

Andy Lester
Andy Lester

Reputation: 93676

Perl is a fine way to do it. Use the -n switch, not -p.

perl -i -l -n -e'print unless /\Q$ENV{FILE}/' filename

Upvotes: 3

Related Questions