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?
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
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
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
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.
I agree -- badly needed.
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
+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?...)
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
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.
Is there any way you can smuggle a convert num(a) in front of this for your macro?