Bash - find a keyword in a file and delete its line

32,968

Solution 1

Use the stream editor, sed:

sed -i ".bak" '/culpa/d' test.txt

The above will delete lines containing culpa in test.txt. It will create a backup of the original (named test.txt.bak) and will modify the original file in-place.

Solution 2

Pipe it to another file, not the same one that you're reading from, and be careful with the useless use of cat.

grep -v "$KEYWORD" /etc/hosts > newfile

Apart from the fine answer given regarding sed, you can also use Perl and a little improved regex to solve this:

perl -pi.old -e 's/.*\sdomain\.com\s*\n//' file

Notice I'm considering domain.com will be isolated by space characters (tabs or spaces, and so on), and that nothing but zero or more spaces will appear after it until the newline. Similarly to -i in sed,
-i.old in perl sets the $^I variable, and your original file will receive the changes while a copy will be kept under the old name and a .old appended.

Solution 3

If you want to only delete last line of your example file

sed -i '/[[:space:]]\+domain\.com/d' test.txt
Share:
32,968
Roger
Author by

Roger

Be the change you want in the world! - M. Gandhi

Updated on July 10, 2022

Comments

  • Roger
    Roger almost 2 years

    I'd like to give a keyword, find the line where this keyword aṕpears in a file and erase the entire line.

    This is what I got but it is not working as it should:

    KEYWORD='domain.com'
    cat /etc/hosts | grep -v "$KEYWORD" > /etc/hosts
    

    UPDATE

    This is what worked for me:

    sed -i_bak -e '/domain\.com/d' /etc/hosts

    However, as I had two lines with "domain.com", is there a way to tell sed to erase only the line where the exact keyword "domain.com" appears

    This is the original content of /etc/hosts:

    127.0.0.1       localhost       localhost.localdomain
    222.111.22.222      hvn.domain.com
    222.111.22.222      domain.com
    

    Here's how it end up after the command sed -i_bak -e '/domain\.com/d' /etc/hosts:

    127.0.0.1       localhost       localhost.localdomain
    

    I tried sed -i_bak -e '/\<namourphoto\.com\.br\>/d' ~/Desktop/hosts but it didn't work.

    CONCLUSION

    This is the code I came up with (based on the help the fine folks have given me):

    D=domain.com
    DOMAIN=`echo "$D" | sed 's/\./\\\\./g'`
    sed -i_bak -e "/[\t]$DOMAIN/d" /etc/hosts
    

    Note that:

    • I am counting that there is always a tab before the domain to be erased

    • I am automatically escaping the dots of the domain name.

    • duri
      duri over 12 years
      Please also note that dot has special meaning in regexps so domain.com will also match domainxcom.net. You should escape the dot.
    • Roger
      Roger over 12 years
      Must I escape dots even when between ''?
    • duri
      duri over 12 years
      Yes, you do. Try echo abc | grep 'a.c', the output will be abc.
    • Roger
      Roger over 12 years
      I wrote a code (above) to do escape the dots automatically
    • chad
      chad over 12 years
      add a space to the [\t] part, since /etc/hosts is whitespace separated.
    • Roger
      Roger over 12 years
      How can I write the regex to choose from space or tab?
    • Roger
      Roger over 12 years
      What if I let the option of a space or a tab? (In my case, it's a tab). Would this be right? /[:space:\t]$DOMAIN/d
  • Roger
    Roger over 12 years
    Is there a way to edit in place with this approach or I always need to make another file in order to edit it?
  • sidyll
    sidyll over 12 years
    @Roger, I updated the answer.
  • Roger
    Roger over 12 years
    Very elegant your code, thank you.
  • Roger
    Roger over 12 years
    My tests didn't work with the space among -i and .bak. But when I pu -i.bak it did work.
  • sidyll
    sidyll over 12 years
    @Roger: De nada, e bonito cachorro. Será que essa área verde aí atrás é aqui em SP? :P
  • Roger
    Roger over 12 years
    origado, é um Akita. Sim, a paisagem é no Morro do Ouro, em Apiaí; conhece?
  • Adam Johns
    Adam Johns about 10 years
    how do you do this while discarding the original without making backup? UPDATE: just made the ".bak" quote blank to answer my own question.
  • Luka
    Luka over 7 years
    in my case keyword is ipaddress with . and port : IS this right? sed -i "/$proxy[^0-9]/d" proxy.txt