Print String array of a json payload in splunk - regex

I need to print a string array along with one field in my json object.
The data:
{ "key1":"val1", "key2":"value2", "codes":["apple","mango","banana","orange"], "key3_conditional":"yes"}
My Search query:
<My search query>
| rex "\|(?<payload>[^\|]*)$"
| spath input=payload
| rex "\"codes\":\"(?<codes>[^\"]*)"
| eval is_unknown=if(isnotnull(key3_conditional), key3_conditional, "no")
| table codes, is_unknown
Desired result
codes | is_unknown
--------------------------------------------------
apple, mango, banana, orange | yes
Currently, this only displays the 1st value in codes i.e. apple and I need all values of codes as comma separated. I'm supposing there is some issue with my regex. Please suggest.

If this data is being brought-in a JSON, you won't have to rex it out
If not, though, the issue is your regular expression
Try it out on regex101.com - you'll see you're only grabbing the first value because you're stopping at a literal "
Try this instead:
...
| rex field=_raw "codes\":\[(?<codes>[^\]]+)"
| eval codes=split(replace(codes,"\"",""),",")
That will make codes into a multivalue field
If you don't care about it being multivalue, you can just do:
| eval codes=replace(codes,"\"","")
to pull the quote marks

Related

How to extract words from a string that end with substrings listed in an array? BigQuery

I have a table of rows with cells containing multiple strings. Like this:
K1111=V1111;K1=V1;kv13_key4=--xxxxxsomething;id5=true;impid=23123123;location=domain_co_uk
I need to extract a substring that begins with kv13_key4= and ends with anything after but the lengths all vary and the substrings are all separated by a semicolon ; . I tried
REGEXP_EXTRACT(customtargeting,'%in2w_key4%;') As contains_key_Value
but didn't work. I need something like this:
| Original Cell | Extracted |
| key88=1811111;id89=9990string;K1=V1;23234234234tttttttt13_key4=--x;id5=true;impid=23123;url=domain_co_uk | kv13_key4=--x |
| K1111=V1111;K1=V1;kv13_key4=--xsomething;id5=true;impid=23123123;location=domain_co_uk | kv13_key4=--xsomething |
| ;id5=true;T6791=V1111;K1=V1;kv13_key4=--xxxxxsomething123;impid=23123 | kv13_key4=--xxxxxsomething123 |
Consider below
select *, regexp_extract(customtargeting, r'kv13_key4=[^;]+') as Extracted
from your_table
if applied to sample data in your question - output is
Does this regex work:
(?<=kv13_key4=)[^;]+(?=;)
It captures everything between 'kv13_key4=' and the nearest ';'
Your REGEX_EXTRACT would look like:
REGEXP_EXTRACT(customtargeting,r'(?<=kv13_key4=)[^;]+(?=;)')

Splunk query not endswith

I am just into learning of Splunk queries, I'm trying to grab a data from myfile.csv file based on the regex expression.
In particular, I'm looking forward, print only the rows where column fqdn not endswith udc.net and htc.com.
Below is my query which is working but i'm writing it twice.
| inputlookup myfile.csv
| regex support_group="^mygroup-Linux$"
| regex u_sec_dom="^Normal Secure$"
| regex fqdn!=".*?udc.net$"
| regex fqdn!=".*?htc.com$"
| where match(fqdn,".")
I am trying them to combine with | separeted but not working though...
| regex fqdn!="(.*?udc.net | ".*?htc.com)$"
You can do this with a search and where clause:
| inputlookup myfile.csv
| search support_group="mygroup-Linux" u_sec_dom="Normal Secure"
| where !match(fqdn,"udc.net$") AND !match(fqdn,"htc.com$")
Or just a single search clause:
| inputlookup myfile.csv
| search support_group="mygroup-Linux" u_sec_dom="Normal Secure" NOT (fqdn IN("*udc.net","*htc.com")
You can also rewrite the IN() thusly:
(fqdn="*udc.net" OR fqdn="*htc.com")
The combined regex will work if you omit the spaces on either side of the |. The extra spaces become part of the regex and prevent matches.
There's no need for the final where command. Splunk by default will display all events that match ..

Unable to format RegEx to handle Dollar Sign ($)

I am stuck trying to figure out how to get a RegEx text search to work with a dollar sign. Let's say I have two strings:
TestPerson One | 123456789 | ($100.00) | $0 | 03/27/2018 | Open
TestPerson Two | 987654321 | ($250.00) | ($25) | 03/27/2018 | Open
Using jQuery, I am creating the RegEx. If I was to search for TestPerson, the RegEx would look like this:
/^(?=.*\bTestPerson).*$/i
This would return both strings, as they both contain TestPerson. If I try and search for $, I get zero results even though both strings contian a $. I know the dollar sign is a special character in RegEx, but escaping it does not work either.
How can I format my RegEx to where searching for $ will return both results?
Thanks!
I think this seems multiline modifier on-off problem. I guess you turned off the multiline modifier and implemented the regex so the unexpected output results. Demo
If you turned on the multiline modifier, you could get the output you want. Demo
To check whether or not a string contains a substring, you don't regex: JavaScript has the string method includes(). This method searches a string for a given value and returns true if it exists in the string and false otherwise.
var a = [
'TestPerson One | 123456789 | ($100.00) | $0 | 03/27/2018 | Open',
'TestPerson Two | 987654321 | ($250.00) | ($25) | 03/27/2018 | Open'
]
a.forEach(function(s) {
console.log(s.includes('TestPerson') && s.includes('$'))
})

How do I select a substring using a regexp in robot framework

In the Robot Framework library called String, there are several keywords that allow us to use a regexp to manipulate a string, but these manipulations don't seem to include selecting a substring from a string.
To clarify, what I intend is to have a price, i.e. € 1234,00 from which I would like to select only the 4 primary digits, meaning I am left with 1234 (which I will convert to an int for use in validation calculations). I have a regexp which will allow me to do that, which is as follows:
(\d+)[\.\,]
If I use Remove String Using Regexp with this regexp I will be left with exactly what I tried to remove. If I use Get Lines Matching Regexp, I will get the entire line rather than just the result I wanted, and if I use Get Regexp Matches I will get the right result except it will be in a list, which I will then have to manipulate again so that doesn't seem optimal.
Did I simply miss the keyword that will allow me to do this or am I forced to write my own custom keyword that will let me do this? I am slightly amazed that this functionality doesn't seem to be available, as this is the first use case I would think of when I think of using a regexp with a string...
You can use the Evaluate keyword to run some python code.
For example:
| Using 'Evaluate' to find a pattern in a string
| | ${string}= | set variable | € 1234,00
| | ${result}= | evaluate | re.search(r'\\d+', '''${string}''').group(0) | re
| | should be equal as strings | ${result} | 1234
Starting with robot framework 2.9 there is a keyword named Get regexp matches, which returns a list of all matches.
For example:
| Using 'Get regexp matches' to find a pattern in a string
| | ${string}= | set variable | € 1234,00
| | ${matches}= | get regexp matches | ${string} | \\d+
| | should be equal as strings | ${matches[0]} | 1234

How to match sub pattern in Robot Framework?

I am doing following things in RFW:
STEP 1 : I need to match the "NUM_FLOWS" value from the following command output.
STEP 2 : If its "Zero - 0" , Testcase should FAIL. If its NON-ZERO, Test case is PASS.
Sample command output:
router-7F2C13#show app stats gmail on TEST/switch1234-15E8CC
--------------------------------------------------------------------------------
APPLICATION BYTES_IN BYTES_OUT NUM_FLOWS
--------------------------------------------------------------------------------
gmail 0 0 4
--------------------------------------------------------------------------------
router-7F2C13#
How to do this with "Should Match Regexp" and "Should Match" keywords? How to check only that number sub-pattern? (Example: In the above command output, NUM_FLOWS is NON-ZERO, Then testcase should PASS.)
Please help me to achieve this.
Thanks in advance.
My New robot file content:
Write show dpi app stats BitTorrent_encrypted on AVC/ap7532-15E8CC
${raw_text} Read Until Regexp .*#
${data[0].num_flows} 0
| | ${data}= | parse output | ${raw_text}
| | Should not be equal as integers | ${data[0].num_flows} | 0
| | ... | Excepted num_flows to be non-zero but it was zero | values=False
There are many ways to solve this. A simple way is to use robot's regular expression keywords to look for "gmail" at the start of a line, and then expect three numbers and then the number 0 (zero) followed by the end of the line. This assumes that a) NUM_FLOWS is always the last column, and b) there is only one line that begins with "gmail". I don't know if those are valid assumptions or not.
Because the data spans multiple lines, the pattern includes (?m) (the multiline flag) so that $ means "end of line" in addition to "end of string".
| | Should not match regexp | ${data} | (?m)\\s+gmail\\s+\\d+\\s+\\d+\\s+0\\s*$
| | ... | Expected non-zero value in the fourth column for gmail, but it was zero.
There are plenty of other ways to solve the problem. For example, if you need to check for other values in other columns, you might want to write a python keyword that parses the data and returns some sort of data structure.
Here's a quick example. It's not bulletproof, and makes some assumptions about the data passed in. I wouldn't use it in production, but it illustrates the technique. The keyword returns a list of items, and each item is a custom object with four attributes: name, bytes_in, bytes_our and num_flows:
# python library
import re
def parse_output(data):
class Data(object):
def __init__(self, raw_text):
columns = re.split(r'\s*', raw_text.strip())
self.name = columns[0]
self.bytes_in = int(columns[1])
self.bytes_out = int(columns[2])
self.num_flows = int(columns[3])
lines = data.split("\n")
result = []
# skip first four lines and the last two
for line in lines[4:-3]:
result.append(Data(line))
return result
Using it in a test:
*** Test Cases ***
| | # <put your code here to get the data from the >
| | # <router and store it in ${raw_text} >
| | ${raw_text}= | ...
| | ${data}= | parse output | ${raw_text}
| | Should not be equal as integers | ${data[0].num_flows} | 0
| | ... | Excepted num_flows to be non-zero but it was zero | values=False