sed delete multi lines after a match then do replace - sed

I have a file /etc/config/network
config interface loopback
option ifname lo
option proto static
option ipaddr 127.0.0.1
option netmask 255.0.0.0
config interface lan
option ifname eth0
option type none
option proto static
option ipaddr 192.168.1.1
option netmask 255.255.255.0
config interface debug
option ifname usb0
option type none
option proto static
option ipaddr 172.18.0.18
option netmask 255.255.255.0
I want to rewrite it to be
config interface loopback
option ifname lo
option proto static
option ipaddr 127.0.0.1
option netmask 255.0.0.0
config interface lan
option ifname eth0
option type none
option proto dhcp
config interface debug
option ifname usb0
option type none
option proto static
option ipaddr 172.18.0.18
option netmask 255.255.255.0
I proceed this in this way:
find static then delete two lines after(exclude line static)
replace static with dhcp
Tried using sed '/static/{n;d}' /etc/config/network | sed -e 's/static/dhcp/' -e '/dhcp/{n;d}' > /etc/config/network which is not so neat.
Could this be like sed -i -e <delete pattern> -e <replace pattern> /etc/config/network ?

I think awk would be a good choice for this type of text processing. It gives you great opportunity for customization.
/^config interface/ { interface=$3; option="" }
$1=="option" { option=$2 }
interface == "lan" && option == "proto" { $3 = "dhcp" }
interface == "lan" && ( option == "ipaddr" || option == "netmask") { option=""; next }
And if the formatting bothers you, you might replace the line that sets $3 with:
interface == "lan" && option == "proto" { gsub(/static/,"dhcp",$0) }
Of course, if you still do want to just one-off this in sed, and the input file is always going to be formatted that way, something like this might be sufficient:
sed '/config interface lan/,/^$/{s/static/dhcp/;/ipaddr/d;/netmask/d;}'
This works by considering the space between "config interface lan" and the next blank line, to restrict the commands to those inside the curly braces. It can adjust to some slight variations in options order, but it needs that blank line.

Using GNU sed
$ sed -i.bak '/config interface lan/,/^$/{/static/{N;N;s/static.*/dhcp/}}' /etc/config/network
config interface loopback
option ifname lo
option proto static
option ipaddr 127.0.0.1
option netmask 255.0.0.0
config interface lan
option ifname eth0
option type none
option proto dhcp
config interface debug
option ifname usb0
option type none
option proto static
option ipaddr 172.18.0.18
option netmask 255.255.255.0

Related

TCPDUMP Syntax filter eth0 traffic to readable file

Attempting to capture traffic but I don't know the write syntax to filter the output to a readable pcap file.
I need to use the syntax
tcpdump -r file.pcap
and to filter eth0 icmp traffic
tcpdump -i eth0 icmp -c 10 > file.pcap
is there a way to do this in one line of command?
Yes, but, if you're writing a pcap file rather than a text file, it doesn't involve the > character.
By default, tcpdump captures traffic from an interface, or reads a capture file, and writes out a human-readable dissection of the packets to the standard output.
You need the -w flag to write out a pcap file, so, in your case, the command is
tcpdump -r file.pcap -w file.pcap ICMP
Your command
tcpdump -i eth0 icmp -c 10 > file.pcap
wouldn't write out a pcap file, it writes out text such as
16:30:59.808885 IP 192.168.1.5 > example.com: ICMP echo request, id 40541, seq 0, length 64
16:30:59.841404 IP example.com > 192.168.1.5: ICMP echo reply, id 40541, seq 0, length 64
If you wanted to write the ICMP traffic to a pcap file, you would do
tcpdump -i eth0 icmp -c 10 -w file.pcap

Command to replace string in one file with content of another file

The file /var/cpanel/mainip contains the main IP of my server and nothing else.
The file /etc/csf/csf.blocklists contains a list of firewall blocklists, and part of the file contains a line with an example IP address 1.2.3.4
Normally when installing CSF firewall software on a new server, I will manually replace the example IP address with the server's main IP address. This is required to successfully fetch firewall blocklists from some providers.
To simplify the setup process, I want a command that will replace the example IP address 1.2.3.4 with my main server IP so I don't have to manually do it.
I've tried a sed command, I guess I'm close to the correct command but not quite there yet. Please can you help?
sed -i '/1.2.3.4/ { r /etc/csf/csf.blocklists }' /var/cpanel/mainip
This code is not right because it outputs an error:
sed: -e expression #1, char 0: unmatched `{'
When successful, it should replace 1.2.3.4 with the actual server IP address.
sed -i "s/1\.2\.3\.4/$(</var/cpanel/mainip)/" /etc/csf/csf.blocklists
should do the job.
You only need to specify
sed -i '/1.2.3.4/r /etc/csf/csf.blocklists' /var/cpanel/mainip
In fact even the space is optional ; following will work too
sed -i '/1.2.3.4/r/etc/csf/csf.blocklists' /var/cpanel/mainip
You are simply specifying the pattern /1.2.3.4/ and a command after that
The command could be r for read, w for write, d for delete and a few others
An example of d to delete the entry would be
sed -i '/1.2.3.4/d' /var/cpanel/mainip

How to replace the second match without replacing the entire line

I have a host file with the below lines:
127.0.0.1
127.0.1.1 servername
The server IP is : 192.168.1.1 which is represented by the IP variable below:
IP=192.168.1.1
I want to replace the second entry that starts with 127.0 with $IP i.e:
instead of :
127.0.1.1 servername
it should be :
192.168.1.1 servername
I tried to use the below sed statement :
sed "0,/127.0.*/! s/127.0.*/$IP/" /etc/hosts
But its replacing the entire line removing the servername as well ,and leave me with :
127.0.0.1 localhost.localdomain localhost
192.168.1.1
its should be :
192.168.1.1 servername
. is a regex-active character, you need to escape it with a backslash (\),
.* will match everything until EOL, use a negated character class for matching everything until first blank character instead.
sed '0,/^127\.0\./! s/^127\.0\.[^[:blank:]]*/'"$IP"'/' file
Btw, you could get this task done way more safely&robustly using awk:
$ awk -v IP="$IP" 'n<2 && index($1,"127.0.")==1 && ++n==2 { $1=IP } 1' file
127.0.0.1
192.168.1.1 servername

Adding scan lines with sed file

I'm trying sed to find test and insert line
example
iface eth0:5 inet static
address 1.1.1.1
netmask 255.255.255.0
iface eth0:6 inet static
address 2.2.2.2
netmask 255.255.255.0
replace
auto eth0:5
iface eth0:5 inet static
address 1.1.1.1
netmask 255.255.255.0
auto eth0:6
iface eth0:6 inet static
address 2.2.2.2
netmask 255.255.255.0
sed should work, but this simple awk can do it too:
awk '/iface/ {print "auto",$2}1' file
auto eth0:5
iface eth0:5 inet static
address 1.1.1.1
netmask 255.255.255.0
auto eth0:6
iface eth0:6 inet static
address 2.2.2.2
netmask 255.255.255.0
Here you go:
sed -e 's/iface \([^ ]*\) .*/auto \1\'$'\n''&/' file
The \([^ ]*\) will capture the name of the interface so we can use by \1 in the replacement, so we can insert as auto \1, followed by a newline, followed by & which means the original line.
If you want to replace inline, you can use the -i flag, for example:
sed -ie 's/iface \([^ ]*\) .*/auto \1\'$'\n''&/' /etc/network/interfaces
If you are OK with perl:
perl -i -lane 'if(/^iface/){print "auto $F[1]\n$_"}else{print}' your_file
Remember this makes an inplace replacement.
If you donot wish for in place replacement then,
perl -lane 'if(/^iface/){print "auto $F[1]\n$_"}else{print}' your_file
You can use awk as well:
awk '/^iface/{print "auto "$2}1' your_file

How to filter tcpdump output based on packet length

I have been trying to filter tcpdump output based on packets lengths. But I had no luck.
This is the simple output for a command;
tcpdump -n -i eth0 dst port 443 -A
17:03:30.866890 IP 192.168.0.149.45104 > 62.75.148.60.443: Flags [S], seq 2685064927, win 14600, options [mss 1460,sackOK,TS val 7028787 ecr 0,nop,wscale 4], length 0
E..<..#.#.......>K.<.0...
........9............
.k#3........
17:03:30.867658 IP 192.168.0.149.45104 > 62.75.148.60.443: Flags [.], ack 2285019097, win 913, options [nop,nop,TS val 7028787 ecr 974439509], length 0
E..4..#.#.......>K.<.0...
...2.............
.k#3:..U
17:03:30.867928 IP 192.168.0.149.45104 > 62.75.148.60.443: Flags [P.], seq 0:171, ack 1, win 913, options [nop,nop,TS val 7028787 ecr 974439509], length 171
E.....#.#..f....>K.<.0...
...2.............
.k#3:..U...........Opw2.....l..".T.7.q.]h..8W..%.....H...
.......9.8.......5... .....E.D.3.2...........A...../.........
...1.........alice.sni.velox.ch.
.................#..
17:03:30.869712 IP 192.168.0.149.45104 > 62.75.148.60.443: Flags [.], ack 1319, win 1078, options [nop,nop,TS val 7028788 ecr 974439511], length 0
E..4..#.#.......>K.<.0...
...2.....6.......
.k#4:..W
17:03:30.870724 IP 192.168.0.149.45104 > 62.75.148.60.443: Flags [P.], seq 171:178, ack 1319, win 1078, options [nop,nop,TS val 7028788 ecr 974439511], length 7
E..;..#.#.......>K.<.0...
...2.....6.......
.k#4:..W......0
I want to see packages only if they have more then 100bytes length. for this case, only the 3rd packet.
options [nop,nop,TS val 7028787 ecr 974439509], length 171
I have looked at man pages for tcpdump, but couldn't find any useful parameter. there is an expression 'greater length' mentioned here; http://www.ethereal.com/docs/man-pages/tcpdump.8.html but i couldn't use that expression too.
$ tcpdump -n -i eth0 dst port 443 -A -x greater 100
tcpdump: syntax error
Thank's for any help.
greater length works, but you have to use it as part of a complete filter expression, and the filter expression has to come after all the command-line flag arguments.
Working example:
tcpdump -n -i eth0 -A -x dst port 443 and greater 100
Should work - dst port 443 and greater 100 is a complete filter expression, which checks for packets that are being sent to TCP or UDP port 443 and that have a total length (including link-layer, IP, and TCP headers!) greater than 100.
NOT working example:
tcpdump -n -i eth0 dst port 443 -A -x greater 100
Will not work - the dst in dst port 443 is treated as the beginning of a filter expression, meaning that it and everything after it, including -A and -x, are treated as part of the filter expression, but -A and -x are not valid components of a filter expression. They are presumably intended to be command-line options, so they must go before all non-flag arguments, including the components of the filter expression.