tags:

views:

86

answers:

4

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   
A: 

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/'

Ether
Seems a bit complex. Does it have any advantage over @andy 's suggestion
justintime
@justintime: nope, andy's solution is better. (I was originally trying to pull a `}{` trick but then realized it wasn't necessary here.)
Ether
Ether thanks for your cooperation
jon
+3  A: 

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
Andy Lester
nice , Andy if I want to check if PATH match the first field in file what I need to change in the perl syntax?
jon
It's not only the "first field" in the file. It's finding $ENV{FILE}'s value anywhere on the line. Also, the \Q turns off the special regex meaning of characters like `.` in $ENV{FILE}.
Andy Lester
YES but I ask if it possible to match only the first field , if it true match only the first field then line will deleted (see my second question)
jon
@jon: add a caret `^` before the `\Q`; or, if you want to allow spaces at the start of the line, add `^\s*` before the `\Q`.
Jonathan Leffler
what to say excellent answer in the right time , your solution is amazing
jon
If you are truly looking at fields, where fields are whitespace separated, you can also look at the -a switch for Perl, which autosplits the input line into a global array @F. See also my slides called "Field Guide To The Perl Command Line" at http://petdance.com/perl/
Andy Lester
A: 
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/^$//

mef
A: 

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.

brian d foy