Splunk Search

is there a cleaner way to zeropad numeric values, ie add leading zeros?

SplunkTrust
SplunkTrust

I have a macro that implements a conversion algorithm. At one point in that algorithm I have to add leading zeros to make sure that a hex value has 8 digits, and not less.

What I've done is a little clunky, and it only zeropads from 7 digits to 8, but in my particular case it's sufficient:

eval myInt=if(len(myInt)==7,"0".myInt,myInt)

Anyone have any suggestions? I see that eval does not have anything obvious here like a zeropad function. I wonder if it would be a good thing to add, or if there's some other way of doing this more cleanly, or in such a way that it can add the correct number of zeros and not just one, with eval or with another command. Any help appreciated.

Tags (2)
1 Solution

Contributor

How about

* | eval myInt="00000000000".tostring(myInt) | eval length=len(tostring(myInt)) | eval trimLength=tonumber(length-3) | eval myInt=tonumber(substr(myInt,trimLength))

There may be some small errors in there as I haven't had the time to test that. In essence, it prepends a bunch of zeros, finds the difference between the length of the string with all the zeros and the total length you want (I chose 3 in the example), and then uses substr() to return only that many digits from the right end of the string.

View solution in original post

SplunkTrust
SplunkTrust

Using printf conversion function this is possible using something like printf("%04d",fieldName). Refer to documentation: https://docs.splunk.com/Documentation/Splunk/latest/SearchReference/ConversionFunctions#Flag_charact...

Following is a run anywhere example:

| makeresults
| fields - _time
| eval data=1
| eval padded_data= printf("%04d",data)
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

Engager

Assuming I know the numbers are always positive and below a certain length, I use a SUBSTR function. For example, to pad out to a 4-digit value
eval formattedNumber=substr("0000".rawNumber,-4)

This worked perfect for me!

SplunkTrust
SplunkTrust

I think the "most correct" option (which does not exist btw) would be a printf-like printed-format function - something like...

| eval newfield=printf("%04.4f %-30s",fieldone, fieldtwo)

I filed an ER asking for this earlier this year - case # 113961. Feel free to tack on a "me too" ER case.

Splunk Employee
Splunk Employee

Good news: this eval function was added in Splunk 6.6 (released today)

Explorer

Thanks Mitch and all the other Splunkers.

0 Karma

New Member

I downvoted this post because it is not a solution, its a would be nice if this works

0 Karma

SplunkTrust
SplunkTrust

We don't usually downvote for items like this, saving downvoting for things that are plainly wrong or might break people's systems. This forum is intended as a place to share and communicate various solutions, and occasionally 'Yes, I filed an enhancement request for this, please join it' is sometimes completely valid.

Motivator

Yes, that looks closest to a "zerofill" function, or "format" function or something. I don't think I filed an ER.

0 Karma

Motivator

How about this - keeps it simple. Use eval to tack on as many zeroes as you'll ever need, then rex to get the last x amount of digits.

Regular

... | eval myint="000000".myint | rex field=myint "(?<myint>\d{6})$"

Hex

... | eval myhex="00000000".myhex | rex field=myhex "(?<myhex>[0-9A-Fa-f]{8})$"

Contributor

How about

* | eval myInt="00000000000".tostring(myInt) | eval length=len(tostring(myInt)) | eval trimLength=tonumber(length-3) | eval myInt=tonumber(substr(myInt,trimLength))

There may be some small errors in there as I haven't had the time to test that. In essence, it prepends a bunch of zeros, finds the difference between the length of the string with all the zeros and the total length you want (I chose 3 in the example), and then uses substr() to return only that many digits from the right end of the string.

View solution in original post

SplunkTrust
SplunkTrust

Not bad. #1) - the 'tonumber' on the end ends up removing all the hard-earned zeros. #2), in my case my values are in hex so I can't use any of the int() stuff.

However you're close. This is similar and works very well.

| eval myVal="1A09" | eval initialLength=len(tostring(myVal)) | eval myVal="0000000000".tostring(myVal) | eval myVal=substr(myVal,initialLength,10)

Builder

You can use rex to first pad the number with "enough" zeroes, then to trim it to the length you require. I broke it into two parts since rex's sed mode doesn't seem to like concatenated commands; I don't know whether you consider this cleaner, but it does allow for variable-length numbers. Let me know if this is useful.


... | rex mode=sed field=myInt "s/(\d+)/00000000\1/" | rex mode=sed field=myInt "s/0*([0-9]{8})/\1/"

SplunkTrust
SplunkTrust

Awesome. No, I like that better than mine. I'll leave the question open for another couple days in case someone has a third way.