We have this table:
And we want to have a field (for example, named "value") that gets the value of the field which name is in the "name" field.
In the first row it would be value=3d, in the second row value would be value=1
Its similar to what
| eval {name} = "whatever"
would do, but reading instead of writing.
(something like | eval value = {name} but that doesn't work).
| eval fieldnames="fieldnames"
| eval fieldvalues="dummy"
| foreach * [| eval fieldnames=if(match("<<FIELD>>","fieldnames|fieldvalues"),fieldnames,mvappend(fieldnames,"<<FIELD>>")) | eval fieldvalues=if(match("<<FIELD>>","fieldnames|fieldvalues"),fieldvalues,mvappend(fieldvalues,<<FIELD>>))]
| eval value=mvindex(fieldvalues,mvfind(fieldnames,name))
| fields - fieldnames fieldvalues
Hi @mseijos, I stumbled accross the same problem and think I got a solution, based on previous contribs:
| makeresults count=10
| fields - _time
| streamstats count
| eval dummyName1="dummyVal1",dummyName2="dummyVal2", name="count", dummyName3="dummyVal3",dummyName4="dummyVal4"
| foreach *
[| eval fieldnames=mvappend(fieldnames,"<<FIELD>>")
| eval fieldvalues=mvappend(fieldvalues,<<FIELD>>)
| eval value=mvindex(fieldvalues,mvfind(fieldnames,name))
]
| fields - dummy* fieldnames fieldvalues
| table count name value
I added dummy values to test the code, as simpler solutions weren't working with a lot of fields per log (because foreach parses all values)
I know it's surely too late for you, but maybe some others will find this interesting.
@HappySplunker
Your solution simplifies OP's requirements. You made an assumption that
name="count"
for every event.
This is not the case.
Here's an updated version to be as close as possible to OP's requirements:
| makeresults count=4
| streamstats count
| eval age = case(count=1, 12, count=2, 25, count=3, 65, count=4, 21)
| eval city = case(count=1, "Paris", count=2, "Berlin",count=3, "Tokyo", count=4, "Madrid")
| eval name = case(count=1, "age", count=2, null(),count=3, "city", count=4, null())
| fields - _time count
| foreach *
[| eval fieldnames=mvappend(fieldnames,"<<FIELD>>")
| eval fieldvalues=mvappend(fieldvalues,<<FIELD>>)
| eval value=mvindex(fieldvalues,mvfind(fieldnames,name))
]
| fields - fieldnames fieldvalues
| eval fieldnames="fieldnames"
| eval fieldvalues="dummy"
| foreach * [| eval fieldnames=if(match("<<FIELD>>","fieldnames|fieldvalues"),fieldnames,mvappend(fieldnames,"<<FIELD>>")) | eval fieldvalues=if(match("<<FIELD>>","fieldnames|fieldvalues"),fieldvalues,mvappend(fieldvalues,<<FIELD>>))]
| eval value=mvindex(fieldvalues,mvfind(fieldnames,name))
| fields - fieldnames fieldvalues
@mseijos - Marking this answer as accepted as it seems working. And it has been answered correctly first. Let me know if this doesn't work for you.
Splunk Community Moderator,
Vatsal Jagani
I needed something like this also.
How about this inefficient solution? It seems to work as long as you get the right fields into the `foreach` part...
| makeresults count=10 | streamstats count
| eval a="1", b="2", name="count"
| foreach * [ eval value=mvindex(mvappend(case(name="<<FIELD>>",'<<FIELD>>'),value),0) ]
Like this:
... | foreach name [ eval value="<<FIELD>>" ]
I tried your solution with this code:
| makeresults
| eval a="1"
| eval b="2"
| eval name="a"
| foreach name [ eval value="<<FIELD>>" ]
But "value" field gets the literal "name" as value. If I remove the quotes in <<FIELD>>
, I get the literal "a" in "value" field.
The expected "value" field would be "1"