want to delete ith matching pattern from file - shell

i want to delete the static entry from dhcpd.cong file by using shell command. Currently I am using sed for the hostname. But there are multiple static entries for same hostname. here is the portion from sample dhcpd.conf file:
host my-system4 {
hardware ethernet 11:22:33:44:55:66;
fixed-address 192.168.17.54;
}
host my-system4 {
hardware ethernet 22:33:44:55:66:77;
fixed-address 192.168.17.34;
}
Here i used:
sed -i '/host my-system4/,/^\}/d' xyz.txt
But this command is deleting all the host my-system4 entries from file. How can I delete the specific entry by doing grep on fixed-address. Also the number of lines under host my-system4 may also vary. I nee shell command which do grep on fixed-address and delete only that specific host entry.

You could say:
sed -e :a -e '/host my-system4/,/}/ { /}/!{ $!{N;ba};};/pattern/d;}' filename
to delete the entry containing the specified pattern.
For example,
sed -e :a -e '/host my-system4/,/}/ { /}/!{ $!{N;ba};};/192\.168\.17\.34/d;}' filename
would delete the entry containing the fixed address 192.168.17.34. Note that . has been escaped so as to match a literal ..
If the entries in the file are guaranteed to be separated by a blank line, you could simplify it by saying:
sed -e '/./{H;$!d;}' -e 'x;/pattern/d' filename
where the pattern in the command above denotes the entry to be deleted.
Add the -i option for in-place editing:
sed -i -e :a -e '/host my-system4/,/}/ { /}/!{ $!{N;ba};};/192\.168\.17\.34/d;}' filename
or
sed -i -e '/./{H;$!d;}' -e 'x;/pattern/d' filename

One solution using vim.
vim -u NONE -N \
-c 'set backup | g/\vfixed-address\s+192\.168\.17\.34/ normal dap' \
-c 'x' infile
It creates a backup of the file appending ~ to the name. Remove set backup and the pipe if you want to risk yourself to lose data. It uses a global replacement to search the line fixed-address 192.168.17.34 and selects the whole paragraph to delete it. The last x command saves the modified file.

Related

Deleting a hosts file entry on solaris using a script or command directly

I have requirement where I want to delete a entry from /etc/hosts file matching a particular entry
For example
I want to delete an entry like below
192.168.1.1 test001 test001.test.test.com
How can I do this either using a single line command or a script.
This deletes the string from your hosts file
sed -i -e "/192.168.1.1 test001 test001.test.test.com/d" filename
You might need regular expressions to catch whitespace between the words which might be blanks or tabs:
sed -i -e "/192.168.1.1.*test001.*test001.test.test.com/d" filename
You can try something like:
grep -v "192.168.1.1 test001 test001.test.test.com" /etc/inet/hosts >/tmp/hosts
mv /tmp/hosts /etc/inet/hosts
The file and path differ because /etc/hosts in Solaris is softlink to /etc/inet/hosts

linux bash insert text at a variable line number in a file

I'm trying to temporarily disable dhcp on all connections in a computer using bash, so I need the process to be reversible. My approach is to comment out lines that contain BOOTPROTO=dhcp, and then insert a line below it with BOOTPROTO=none. I'm not sure of the correct syntax to make sed understand the line number stored in the $insertLine variable.
fileList=$(ls /etc/sysconfig/network-scripts | grep ^ifcfg)
path="/etc/sysconfig/network-scripts/"
for file in $fileList
do
echo "looking for dhcp entry in $file"
if [ $(cat $path$file | grep ^BOOTPROTO=dhcp) ]; then
echo "disabling dhcp in $file"
editLine=$(grep -n ^BOOTPROTO=dhcp /$path$file | cut -d : -f 1 )
#comment out the original dhcp value
sed -i "s/BOOTPROTO=dhcp/#BOOTPROTO=dhcp/g" $path$file
#insert a line below it with value of none.
((insertLine=$editLine+1))
sed "$($insertLine)iBOOTPROTO=none" $path$file
fi
done
Any help using sed or other stream editor greatly appreciated. I'm using RHEL 6.
The sed editor should be able to do the job, without having to to be combine bash, grep, cat, etc. Easier to test, and more reliable.
The whole scripts can be simplified to the below. It performs all operations (substitution and the insert) with a single pass using multiple sed scriptlets.
#! /bin/sh
for file in $(grep -l "^BOOTPROTO=dhcp" /etc/sysconfig/network-scripts/ifcfg*) ; do
sed -i -e "s/BOOTPROTO=dhcp/#BOOTPROTO=dhcp/g" -e "/BOOTPROTO=dhcp/i BOOTPROTO=none" $file
done
As side note consider NOT using path as variable to avoid possible confusion with the 'PATH` environment variable.
Writing it up, your attempt with the following fails:
sed "$($insertLine)iBOOTPROTO=none" $path$file
because:
$($insertLine) encloses $insertLIne in a command substitution which when $insertLIne is evaluated it returns a number which is not a command generating an error.
your call to sed does not include the -i option to edit the file $path$file in place.
You can correct the issues with:
sed -i "${insertLine}i BOOTPROTO=none" $path$file
Which is just sed - i (edit in place) and Ni where N is the number of the line to insert followed by the content to insert and finally what file to insert it in. You add ${..} to insertLine to protect the variable name from the i that follows and then the expression is double-quoted to allow variable expansion.
Let me know if you have any further questions.
(and see dash-o's answer for refactoring the whole thing to simply use sed to make the change without spawning 10 other subshells)

SED command to add or update IP address from variable to /etc/network/interfaces

I am developing a deployment script "that I want to be able to run over again without double entries"
I am trying to add a sed command that will look for "address" field, if it doesn't exist, create it, if it does exist modify it to the correct IP Address.
This is what I have so far...
#!/bin/bash
ipaddress=192.168.1.1
sudo grep -q '^address' /etc/network/interfaces && sudo sed -i 's/^address.*/"address $ipaddress"/' /etc/network/interfaces || echo "address ${ipaddress}" >> /etc/network/interfaces
It will create the correct entry if no entry exists but I have all kinds of problems if the entry exists or is correct.
Any help would be greatly appreciated!
Final Answer based on response from "1stSi Dave" Below
The final working script that creates the entry if it doesn't exist or alters any existing address entry is:
sudo grep -q '^address' /etc/network/interfaces && sudo sed -i -e 's/^address.*/address '$ipaddress'/' /etc/network/interfaces || echo "address ${ipaddress}" >> /etc/network/interfaces
First, I think you need the '-e' command line option to your sed command:
sed -i -e 's/...'
Maybe that's a typo, because the rest of your command line indicates you want to append to the file, not edit in place. Next, single quotes are hiding the variable expansion you're trying to achieve in the sed command script. They are also preserving the double quotes in the output, which I don't think is what you want. Try this:
sed -e 's/^address.*/address '$ipaddress'/' /etc/network/interfaces
Third, you may want to include the possibility of white space preceding the "address" token. Finally, you probably do want to edit-in-place (with sed -i), because tacking on the edited line at the end of the file is probably not going to work.

Remove filenames from Textfile with sed

I would like to delete filenames from a textfile to have as output only the folder.
Example:
Creature\FrostwolfPup\FrostWolfPup_Shadow.m2
Creature\FrostwolfPup\FrostWolfPup_Fire.m2
To
Creature\FrostwolfPup\
To match only the Filenames i use [^\\]*$
Now i put it together with sed while /d should delete it
D:\filetype\core\sed.exe -n -e "/^[^\\]*$/d" D:\filetype\listfile\archive\tmp\all.txt > D:\filetype\module\model_bruteforce\tmp\folders_tmp1.txt
But instead of a textfile with my folders i got only a empty textfile as output, and so something must be wrong.
Tested on linux, not cygwin
sed -r 's/[^\\]*$//g' /path/to/original/file > /path/to/new/file
Try:
sed.exe -e "s/[^\\]*$//" path/to/folders.txt
The command s/[^\\]*$// asks sed to remove everything after the last \ on a line to the end of the line.
Caveat: since I don't have a windows machine handy for testing, I am unsure if the backslashes need to be doubled as shown above.
Discussion
-n tells sed not print anything unless we explicitly ask it to. The following command never asks sed to print:
sed.exe -n -e "/^[^\\]*$/d"
Consequently, it produces no output.

Unix script to delete the first line of a file on a Mac

On my Mac, when I try to run:
sed -i 2d file.csv
from the answer to Unix script to remove the first line of a CSV file, I get the following error:
sed: 1: "file.csv": invalid command code f
What can I do if I would like to delete the first two lines of file.csv?
On a Mac, the BSD sed requires the suffix for the backup (but the suffix can be an empty string, '') — it is not optional as it is with GNU sed. Hence, your command is being interpreted as "backup the file with the suffix 2d and … oops, the script you gave is file.csv, but f isn't a sed command".
sed -i .bak -e 2d file.csv
This deletes the first line of data from the CSV file (leaving the heading line in place).
If you want to write the code so it works with both BSD and GNU sed, then you have to attach the suffix to the -i option (GNU sed requires the suffix attached to the -i option; that's how it identifies whether there's an optional suffix or not):
sed -i.bak -e 2d file.csv
Note that you can't use an empty suffix and have the command work with both BSD sed and GNU sed.
The -e isn't necessary in either command line, but I quite often use it. I also often quote the command in single quotes, though it isn't necessary here.
If you want to delete the first two data lines, use 2,3d as the command. If you want to delete the first two lines, use 1,2d.
If you don't want the backup, then you can either remove it after the sed command completes (easiest) or use the two stage or three stage dance:
sed 2d file.csv > file.csv.bak &&
mv file.csv.bak file.csv # Oops; there went the links
sed 2d file.csv > file.csv.bak &&
cp file.csv.bak file.csv
rm -f file.csv.bak
With these, you might need to add trap commands to clean up the intermediate .bak file if an interrupt or other signal terminates the script.
To quote from the Apple documentation for sed — which was originally quoted by Diego in an answer which he chose to delete, the -i option takes an argument which indicates the extension to use for backup copies.
-i extension
Edit files in-place, saving backups with the specified extension. If a zero-length extension is given, no backup will be saved. It is not recommended to give a zero-length extension when in-place editing files, as you risk corruption or partial content in situations where disk space is exhausted, etc.
sed -i.bak '2,3d' filename.csv will delete lines 1 and 2 (assuming you have headers)
What this command does is edits the file being referenced while simultaneously creating a backup of the original file (hence the usage of .bak). The line deletion '2,3d' will delete the 2nd and 3rd line of the original file.

Resources