0

I have a file that contains a list of DHCP bindings. I want to extract some of the data, however its not as straight forward as it first appeared it would be, often the hardware identifier is across multiple lines.

You can see those in the second column, they have a period at the end when they continue onto the next line.

So to sum up what I want to achieve here. Extract column 1 and 2 where there is an IP address and just column 2 where there is none, the end result being the IP and full hardware address on a single line.

The goal being to make it faster to get the hardware identifier, currently if I want to assign a static IP I have to perform up to three copy/pastes, not a big deal I know, but I would still like to be able to do it in one copy.

Data example:

10.x.x.x            ff9f.6e85.2400.0200.    Infinite                Manual
                    00ab.1146.a45b.6916.
                    7ae3.be
10.x.x.x            ff29.ed05.1200.0100.    Infinite                Manual
                    0128.c2e3.9300.0c29.
                    ed05.12
10.x.x.x            ff9f.6e85.2400.0200.    Infinite                Manual
                    00ab.11e7.d0ba.2f43.
                    f135.f2
10.x.x.x            ff9f.6e85.2400.0200.    Infinite                Manual
                    00ab.11b2.f37a.8a39.
                    e6bf.93
10.x.x.x            ff9f.6e85.2400.0200.    Infinite                Manual
                    00ab.115c.5da2.eecf.
                    09d7.41
10.x.x.x            000c.29a0.40a3          Feb 07 2022 05:44 PM    Automatic
10.x.x.x            01e8.3935.e98c.14       Infinite                Manual
10.x.x.x            0168.b599.bed2.94       Infinite                Manual
10.x.x.x            01d0.67e5.0530.ef       Feb 07 2022 11:54 PM    Automatic
10.x.x.x            ff29.a040.a300.0100.    Infinite                Manual
                    0129.88be.c700.0c29.
                    a040.a3

The following code I have managed to put together looking around for a solution. Searches like "awk if column 1 = ip address" came back with the regex, I am not even sure that I am using it correctly.

awk '{
    if ($1~/^[[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\]/) {
        ip="\n$1"
        addr=$2
    } else {
        addr="$1"
    }
    printf "%s %s",ip,addr;
}' data.txt

I am aware I need some way to combine the addr variable too, I can work on that later, just getting the columns correctly would be a massive help. (Think I sorted the combining part, adjusted the code to the following, removing the variables.)

awk '{
    if ($1~/^[[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\]/) {
        printf "\nIP Address: %s", $1
        printf $2
    } else {
        printf $1
    }
}' data.txt

So, if I can get help with how to check if the first column contains an IP address I should be there.

CodingInTheUK
  • 930
  • 7
  • 16

2 Answers2

1

It seems like the task here is to reformat a table.

awk '
l && /^[^[:space:]]/ {print l; l=""}
/^[^[:space:]]/ {l = "IP Address: "$1" "$2; next}
l {l = l$1}
END {if (l) {print l}}'

Prints:

IP Address: 10.x.x.x ff9f.6e85.2400.0200.00ab.1146.a45b.6916.7ae3.be
IP Address: 10.x.x.x ff29.ed05.1200.0100.0128.c2e3.9300.0c29.ed05.12
IP Address: 10.x.x.x ff9f.6e85.2400.0200.00ab.11e7.d0ba.2f43.f135.f2
IP Address: 10.x.x.x ff9f.6e85.2400.0200.00ab.11b2.f37a.8a39.e6bf.93
IP Address: 10.x.x.x ff9f.6e85.2400.0200.00ab.115c.5da2.eecf.09d7.41
IP Address: 10.x.x.x 000c.29a0.40a3
IP Address: 10.x.x.x 01e8.3935.e98c.14
IP Address: 10.x.x.x 0168.b599.bed2.94
IP Address: 10.x.x.x 01d0.67e5.0530.ef
IP Address: 10.x.x.x ff29.a040.a300.0100.0129.88be.c700.0c29.a040.a3

This works by checking if a line begins with a space (padding) or not (IP Address).

dan
  • 4,846
  • 6
  • 15
0

I have solved my problem with help from this Answer to another question

It turns out I had the correct regex in the first place but had not implemented it correctly, when i tried it I missed the part about posix being for the command line and put it inside the if along with the regex. Positioning it outside of the braces solved it.

Here is my updated code with a regex to match an ip address in the first column.

awk --posix '{
    if ($1 ~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/) {
        printf "\nIP Address: %s %s", $1, $2
    } else {
        printf $1
    }
}' data.txt
echo ""

And the result:

IP Address: 10.x.x.x ff9f.6e85.2400.0200.00ab.1146.a45b.6916.7ae3.be
IP Address: 10.x.x.x ff29.ed05.1200.0100.0128.c2e3.9300.0c29.ed05.12
IP Address: 10.x.x.x ff9f.6e85.2400.0200.00ab.11e7.d0ba.2f43.f135.f2
IP Address: 10.x.x.x ff9f.6e85.2400.0200.00ab.11b2.f37a.8a39.e6bf.93
IP Address: 10.x.x.x ff9f.6e85.2400.0200.00ab.115c.5da2.eecf.09d7.41
IP Address: 10.x.x.x 000c.29a0.40a3
IP Address: 10.x.x.x 01e8.3935.e98c.14
IP Address: 10.x.x.x 0168.b599.bed2.94
IP Address: 10.x.x.x 01d0.67e5.0530.ef
IP Address: 10.x.x.x ff29.a040.a300.0100.0129.88be.c700.0c29.a040.a3

It's exactly how I wanted it. (added the echo to put the terminal prompt back on it's own line).

CodingInTheUK
  • 930
  • 7
  • 16
  • 1
    Things are a bit more involved. You will want to take a look at [Validating IPv4 addresses with regexp](https://stackoverflow.com/q/5284147/3422102) – David C. Rankin Feb 07 '22 at 03:15
  • There is no need to in this case as the data comes from existing DHCP clients of my router. But thank you for the link, I will certainly be interested in what it shows up, I am just getting into coding on my linux system so the more I can learn the better prepared. Again, thank you. – CodingInTheUK Feb 07 '22 at 03:22
  • Good. As long as you can confirm the limits of what your IPs will be, you will be fine with what you have. Just be aware of the additional caveats if things change. – David C. Rankin Feb 07 '22 at 03:24