LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-30-2017, 03:21 AM   #1
ddaas
Member
 
Registered: Oct 2004
Location: Romania
Distribution: Ubuntu server, FreeBsd
Posts: 474

Rep: Reputation: 30
remove part of a text file based on a string pattern


Hi there,
I want a bash script that removes part of a text file based on a specific pattern.
For example let's take the dhcpd.conf that contains many host containers like this:

host dellxx {
hardware ethernet 01:23:47AC:99:14;
fixed-address 10.0.0.1;

}


I want my script to take the MAC as argument and remove that host.
Like: ./remome_host 01:23:47AC:99:14
and it removes:
host dellxx {
hardware ethernet 01:23:47AC:99:14;
fixed-address 10.0.0.1;

}


How cad I do that in bash? I thaught about awk.

Thank you
 
Old 01-30-2017, 03:24 AM   #2
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,303
Blog Entries: 3

Rep: Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720
That's doable in sed, awk, or perl. Which one are you trying? Can you show us how far you have gotten and where you are stuck?
 
Old 01-30-2017, 03:36 AM   #3
ddaas
Member
 
Registered: Oct 2004
Location: Romania
Distribution: Ubuntu server, FreeBsd
Posts: 474

Original Poster
Rep: Reputation: 30
I tried in awk but I am beginner. I'll put everything together and show you here.
Thanks
 
Old 01-30-2017, 06:06 AM   #4
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,303
Blog Entries: 3

Rep: Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720
Great. In sed and awk, you don't get much flexibility so don't try to make a generic dhcpd.conf parser. Just make one for your use case. If you need something bigger, fancier, or more complex then escalate to perl and try Net::ISC::DHCPd
 
Old 01-30-2017, 12:54 PM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
I would add that this is doable in bash, but awk and others are easier and probably preferable based on the task

Like many others, please remember to include a proper example, ie. a file that has both what needs to be removed and what needs to be kept.
Also include the output of the operation so it is unambiguous as to your need.

Lastly, please use [code][/code] tags around both code and example data.
 
Old 01-31-2017, 01:10 PM   #6
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,789

Rep: Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201
Here is an awk solution
Code:
awk '
{
  if (b==0 && NR>1) {
    if (!found) { print buf } else { found=0 }
    buf=sep=""
  }
  if (index($0,search)) found=1
  b+=gsub(/\{/,"&")-gsub(/\}/,"&")
  buf=buf sep $0; sep=ORS
}
END {
  if (NR>1) if (!found) print buf
}
' search="01:23:47AC:99:14" file
Short explanation: the lines are stored into a string buffer. If leaving the { } block the buffer is printed if no search was met.

Last edited by MadeInGermany; 02-01-2017 at 02:39 AM. Reason: "\{" could give a warning
 
1 members found this post helpful.
Old 01-31-2017, 01:20 PM   #7
szboardstretcher
Senior Member
 
Registered: Aug 2006
Location: Detroit, MI
Distribution: GNU/Linux systemd
Posts: 4,278

Rep: Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694
I've gotten part of it. This will return the searched for block:

Code:
awk -v RS='[^\n]*{|}' 'RT ~ /{/{p=RT} /01:23:47AC:99:14/{ print p $0 RT }' inputfile
 
1 members found this post helpful.
Old 01-31-2017, 01:31 PM   #8
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,303
Blog Entries: 3

Rep: Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720
Quote:
Originally Posted by szboardstretcher View Post
I've gotten part of it. This will return the searched for block:

Code:
awk -v RS='[^\n]*{|}' 'RT ~ /{/{p=RT} /01:23:47AC:99:14/{ print p $0 RT }' inputfile
Sweet. I hadn't seen RT before.

RT is only in gawk though. Debian-derivative systems seem to use mawk but gawk can be added.

dhcpd.conf files can be much more complex and ddaas might (or might not) have published just an excerpt.
 
1 members found this post helpful.
Old 01-31-2017, 01:39 PM   #9
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,830

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
in awk it looks quite simple:
the "usual" way is to set the RS to a keyword, like \nhost<space> (or something similar), and now you can skip "lines" containing the given filter.
Code:
awk -v RS='\nhost ' '/01:23:47AC:99:14/{next}1' inputfile

Last edited by pan64; 01-31-2017 at 01:40 PM.
 
1 members found this post helpful.
Old 01-31-2017, 02:01 PM   #10
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,789

Rep: Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201
pan64, the RS is missing in the output. You need to extra print it
Code:
awk 'BEGIN{RS="\nhost "} /01:23:47AC:99:14/{next} {print (NR>1?RS $0:$0)}' file
 
Old 02-01-2017, 12:37 AM   #11
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,830

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
there was a 1, probably you missed:
Code:
awk -v RS='\nhost ' '/01:23:47AC:99:14/{next}1' inputfile
 
Old 02-01-2017, 12:46 AM   #12
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,303
Blog Entries: 3

Rep: Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720Reputation: 3720
Quote:
Originally Posted by pan64 View Post
there was a 1, probably you missed:
Code:
awk -v RS='\nhost ' '/01:23:47AC:99:14/{next}1' inputfile
Even with the 1 it will show "host foo {" for the first record and then just "bar {" for the subsequent records.
The ORS needs to be set, too:

Code:
awk -v RS='\nhost ' -v ORS='\nhost ' '/01:23:47AC:99:14/{next}1' inputfile

Last edited by Turbocapitalist; 02-01-2017 at 12:48 AM.
 
Old 02-01-2017, 01:20 AM   #13
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,830

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
yes, you are right. thanks
 
Old 02-01-2017, 04:19 AM   #14
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Quote:
Originally Posted by Turbocapitalist View Post
Even with the 1 it will show "host foo {" for the first record and then just "bar {" for the subsequent records.
The ORS needs to be set, too:

Code:
awk -v RS='\nhost ' -v ORS='\nhost ' '/01:23:47AC:99:14/{next}1' inputfile
The above seems to leave a dangling 'host'
 
Old 02-01-2017, 05:49 AM   #15
ddaas
Member
 
Registered: Oct 2004
Location: Romania
Distribution: Ubuntu server, FreeBsd
Posts: 474

Original Poster
Rep: Reputation: 30
The solution from MadeInGermany works great. I dind't understand everything, but I am on my way..
Also the first solution from szboardstretcher is ok. It returns the searched string, I still have to remove that from the initial file.



The dhcpd.conf file looks like that:

Code:
 authoritative;
option domain-name "mydomain.com";
option domain-name-servers 8.8.4.4,8.8.8.8;
default-lease-time 6000;
max-lease-time 72000;
log-facility local7;


subnet 192.168.0.0 netmask 255.255.255.0 {    
        range                      192.168.0.10 192.168.0.100;
        allow                       unknown-clients;
        default-lease-time          3600;    
        max-lease-time              64000;    
        option routers                     192.168.0.1;
        option subnet-mask                 255.255.255.0;
        option domain-name-servers         8.8.8.8;
        option ntp-servers    	           192.168.0.1;
        option domain-name                  "mydomain.com";
        
        
}
 
host hp1 {
           hardware ethernet         01:AF:55:F6:B0:22;
           fixed-address                192.168.0.130;
           option routers               192.168.0.254;
}
   


host hp2 {
           hardware ethernet        01:AF:55:F6:B0:23;
           fixed-address                192.168.0.131;
}
   

host hp3 {
           hardware ethernet        01:AF:55:F6:B0:24;
           fixed-address                192.168.0.13;
}
  
#and so on
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Remove End of string from pattern Ra'Jiska Linux - Newbie 7 10-16-2015 06:29 AM
How to remove string in the text file ? Bash script dlugasx Linux - Server 9 06-05-2009 11:40 AM
Remove lines in a text file based on another text file asiandude Programming 10 01-29-2009 10:59 AM
Bash remove part of a file based on contents of another file bhepdogg Programming 4 01-31-2007 03:13 PM
Find string pattern in directory of text files magnum818 Linux - Newbie 2 10-15-2003 08:19 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:38 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration