Thursday, January 3, 2013

Go Lang and regex

If you have more than one physical or virtual ethernet port or WiFi or a combination then you may also have more than one IP address assigned to your system. Of course it's also possible when you use CARP or other high availability strategy or even network tunnel. And this is not limited to Linux but also Windows machines.

Without actually deciding which IP address is the correct IP address let's use Go and it's exec and regexp libraries to get that information in the most Unix way.

The following command, when completed without an err,  will return the output of the Windows command "ipconfig /all". Therefore the variable out will have a multiline string or a string which contains newline chars.
out, err := exec.Command("ipconfig", "/all").Output()
Now that we have some output, in the form of a string, we should look at the output. Well, I'm not going to copy/paste 100 lines of output here.  Suffice to say that the lines that we are looking for look like this:
IPv4 Address . . . . . . . : 10.10.10.10(Preferred)
There's nothing fancy about this sort of regex but what we are looking for are lines with this format. As a side note I believe that the (Preferred) is optional on the output of the command. The following command compiles the regular expression for use by subsequent Find() functions. Also as time progressed the regex improved.
re, err := regexp.Compile(`(?m)^\s*IPv4 Address(.*)$`)
The regex above is pretty simple. Since Go uses re2 there is a flag (?m) that tells the compiler that the input string contains multiple lines. If I did not add this flag then I would have to split() the string and then run the re on each line separately.

The following function will convert my output data from a []byte to a string and then run the regular expression previously compiled against that string. (The -1 is not completely documented but a -1 seems to be the best value and indicates the number of bytes in the target search string). This function returns a list of all of the matches.
ips := re.FindAllString(string(out),-1)
Alternatively, the following will extract an exact list of IP address.
re, err := regexp.Compile(`(?m)^\s*IPv4 Address\s*:\s(([0-9]\.){3}([0-9]))\s*$`)
 When used with this function.
ips := re.FindAllStringSubmatch(string(out),-1)
 Go's regexp is pretty powerful and the key to the success of this project.

No comments:

Post a Comment

another bad day for open source

One of the hallmarks of a good open source project is just how complicated it is to install, configure and maintain. Happily gitlab and the ...