Splunk Search
Highlighted

How to force "eval" to cast an expression as numeric value?

Super Champion

Let's say you have two fields like so:

a=0001L
b=0002L

What's the best way to force the eval command to see these as numeric fields so that you can add these two values together. It seems like you should be able to simply say something like:

... | eval c=rtrim(a,"L") + rtrim(b,"L")

However, "c" ends up with the value "00010002" instead of 3 because within the scope of that individual eval splunk thinks the output of both rtrim as strings and not as numeric values.

To quickly test this yourself, you can run this contrived search command:

* | head 1 | a="0001L" | eval b="0002L" | eval c=rtrim(a,"L") + rtrim(b,"L") | fields a b c

So the question is this:

Is there anyway to force eval to cast the output of an expressions to a numeric value, so that "+" becomes a mathematical operation and not a string concatenation?


Yes, I realize that simply breaking this into multiple evals solves this problem, like so:

...  eval _a=rtrim(a,"L") | eval _b=rtrim(b,"L") | eval c= _a+_b

However, this does NOT work for my use case. I am attempting to write an eval-based macro expression which must be a single eval, not a series of evals. Therefore, all the work has to be done in a single eval.

I guess I'm looking for counterpart of tostring. Is there some an undocumented "tonumber()" or similar function?

Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Motivator

Is there any way you can smuggle a convert num(a) in front of this for your macro?

0 Karma
Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Super Champion

Nope. It has to be within a single eval expression. Since my macro is eval-based, I can't even do any kind of nested macro tricks.

0 Karma
Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Splunk Employee
Splunk Employee

If the values really are all single digits with 0s prepended, I have (a very ugly) solution for you. The one function that maps string to num, is len. Ready? First, strip the 0s. Then, replace 1 with a single x, 2 with xx, and so forth. And finally, we can invoke len on the resulting string (xx maps to 2😞

* | head 1 | eval a="0001L" | eval b="0002L" | eval c=len(replace(replace(replace(rtrim(a,"L"), "0", ""), "1", "x"), "2", "xx")) + len(replace(replace(replace(rtrim(b,"L"), "0", ""), "1", "y"), "2", "yy")) | table a b c

gives

  a     b   c
----- ----- -
0001L 0002L 3
Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Super Champion

Wow. That's hilarious. But no, in my particular use case I'm looking at a time field. So mapping 0-23 and 0-59 within a single eval using this approach would be quite ugly. (I'd have to write a script just to generate my eval command.) Then I'd probably run into some eval expression character limit... I found a 4.1-based workaround using regex-based replace() and relative_time(), which you can see here (if your interested): http://answers.splunk.com/questions/4528/finding-your-local-timezone-with-eval

0 Karma
Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Super Champion

+1. Just for the craziness of this solution. (I do wonder how far this would stretch. Is the eval handled in a stack-based way, would you eventual end up with a stack overflow?...)

Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Explorer

Yeah, it looks like a tonumber() function is a badly needed addition to the language. I'm going to file a bug report right now.

The one (gross) workaround that I can think of is to abuse the strptime() time parser. This would only work on non-negative integers, but it might be enough for your immediate issue:

$ splunk search '* | head 1 | eval a="0001L" | eval b="0002L" | eval c=strptime(rtrim(a,"L"),"%s") + strptime(rtrim(b,"L"),"%s") | table a b c'
  a     b      c
----- ----- --------
0001L 0002L 3.000000

View solution in original post

Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Motivator

I agree -- badly needed.

0 Karma
Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Super Champion

Thanks for filing a request. I found a workaround for my specific needs using relative_time(). But there are certainly other cases where such a solution wouldn't work, so a tonumber(), or whatever it ends up being called would be greatly appreciated.

0 Karma
Highlighted

Re: How to force "eval" to cast an expression as numeric value?

Splunk Employee
Splunk Employee

In 4.1.5, the eval command now includes a tonumber() function.

For reference: http://www.splunk.com/base/Documentation/4.1.5/SearchReference/CommonEvalFunctions