Print only part of a match using grep

I am wondering if I can use one grep command for the following situation.

I have a dhcpd.conf file in which DHCP hosts are defined. Given the host name, I need to find its MAC address in the dhcpd.conf file. I need to use it to disable its PXE boot configuration, but this is not part of this question.

The file syntax is homogeneous, but I still want to make it a little dumb. Here's how nodes are defined:

    host client1 { hardware ethernet 12:23:34:56:78:89; fixed-address 192.168.1.11; filename "pxelinux.0"; }
    host client2 { hardware ethernet 23:34:45:56:67:78; fixed-address 192.168.1.12; filename "pxelinux.0"; }
    host client3 { hardware ethernet AB:CD:EF:01:23:45; fixed-address 192.168.1.13; filename "pxelinux.0"; }
    host client4 { hardware ethernet C1:CA:88:FA:F4:90; fixed-address 192.168.1.14; filename "pxelinux.0"; }

We assume that all configurations occupy only one line, even if the syntax dhcpd.conf allows you to split the parameters into several lines. Assume that the order of options may vary.

I came up with the following grep command:

grep -o "^[^#]*host.*${DHCP_HOSTNAME}.*hardware ethernet.*..:..:..:..:..:..;" /etc/dhcp/dhcpd-hosts.conf

, , MAC-. , :

host client1 { hardware ethernet 12:23:34:56:78:89;

! , MAC- . , grep, cut, awk MAC- . , grep ? , , , "..:..:..:..:..:.." MAC-.

, ( grep), MAC- . - , "grep... | grep..." "grep... | cut..." ..

, , , , .

.

+4
4

sed , :

sed -e "/host  *${DHCP_HOSTNAME}/!d" -e "s/*.\(hardware [^;]*\).*/\1/g"

, ${DHCP_HOSTNAME} ( , - , , ).

.

+1

Perl , , , .

Perl . idiom perl -ne {program}, stdin {program} , $_. (. -n $_ , -p, perl -pe {program}.)

. , , -s, {program}, awk -v. ( -n, while (<>) { ... } , -s . . @ARGV -n -p?. $DHCP_HOSTNAME {program} string, ( 8) .

DHCP_HOSTNAME='client3';
perl -nse 'print($1) if m(^\s*host\s*$host\s*\{.*\bhardware\s*ethernet\s*(..:..:..:..:..:..));' -- -host="$DHCP_HOSTNAME" <dhcpd.cfg;
## AB:CD:EF:01:23:45

Perl sed :

+1

Grep -o :

grep -o "[0-9A-F]\{2\}:[0-9A-F]\{2\}:[0-9A-F]\{2\}:[0-9A-F]\{2\}:[0-9A-F]\{2\}:[0-9A-F]\{2\}"

:

12: 23: 34: 56: 78: 89
23: 34: 45: 56: 67: 78
AB: CD: EF: 01: 23: 45
C1: CA: 88: FA: F4: 90

MAC- dhcp.

0
source

Since people also respond with different tools, I think that awkmight be a good alternative.

$ cat so
host client1 { hardware ethernet 12:23:34:56:78:89; fixed-address 192.168.1.11; filename "pxelinux.0"; }
host client2 { hardware ethernet 23:34:45:56:67:78; fixed-address 192.168.1.12; filename "pxelinux.0"; }
#host client3 { hardware ethernet AB:CD:EF:01:23:45; fixed-address 192.168.1.13; filename "pxelinux.0"; }
host client3 { hardware ethernet AB:CD:EF:01:23:45; fixed-address 192.168.1.13; filename "pxelinux.0"; }
host client4 { hardware ethernet C1:CA:88:FA:F4:90; fixed-address 192.168.1.14; filename "pxelinux.0"; }
$ awk '/^[^#]/ && /client3/ { printf ("%s: %s\n",  $2, $6); }' so
client3: AB:CD:EF:01:23:45;

I use double matching to exclude commented out lines and just use the field index to print the required information. Thus, it should also be easy to remove part of the PXE. For example, filenameyou can remove the directive for host3 as follows:

$ awk '/^[^#]/ && /client3/ { gsub(/filename[^;]+;/, ""); print; }' so
host client3 { hardware ethernet AB:CD:EF:01:23:45; fixed-address 192.168.1.13;  }

Specifying a custom image (pxecustom.0):

$ awk '/^[^#]/ && /client3/ { gsub(/filename[^;]+;/, "filename \"pxecustom.0\";"); print; }' so
host client3 { hardware ethernet AB:CD:EF:01:23:45; fixed-address 192.168.1.13; filename "pxecustom.0"; }
0
source

Source: https://habr.com/ru/post/1653015/


All Articles