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

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!

#### Introducing the Splunk Community Dashboard Challenge!

Welcome to Splunk Community Dashboard Challenge! This is your chance to showcase your skills in creating ...

#### Get the T-shirt to Prove You Survived Splunk University Bootcamp

As if Splunk University, in Las Vegas, in-person, with three days of bootcamps and labs weren’t enough, now ...

#### Wondering How to Build Resiliency in the Cloud?

IT leaders are choosing Splunk Cloud as an ideal cloud transformation platform to drive business resilience,  ...