Splunk Search

## 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 `eval`s 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?

Tags (3)
1 Solution
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
``````
Splunk Employee

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

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
``````
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.

Motivator

I agree -- badly needed.

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 `0`s. 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
``````
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?...)

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

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.

Motivator

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

Get Updates on the Splunk Community!

#### Stay Connected: Your Guide to July and August Tech Talks, Office Hours, and Webinars!

Dive into our sizzling summer lineup for July and August Community Office Hours and Tech Talks. Scroll down to ...

#### Edge Processor Scaling, Energy & Manufacturing Use Cases, and More New Articles on ...

Splunk Lantern is a Splunk customer success center that provides advice from Splunk experts on valuable data ...

#### Get More Out of Your Security Practice With a SIEM

Get More Out of Your Security Practice With a SIEMWednesday, July 31, 2024  |  11AM PT / 2PM ETREGISTER ...