Unable to capture required string from text file using Groovy - Jmeter JSR223 - regex

I need to parse a text file testresults.txt and capture serial number and then write the captured serial number onto separate text file called serialno.txt using groovy Jmeter JSR223 post processor.
Below code is not working. It didn't get into the while loop itself. Kindly help.
import java.util.regex.Pattern
import java.util.regex.Matcher
String filecontent = new File("C:/device/resources/testresults.txt").text
def regex = "SerialNumber\" value=\"(.+)\""
java.util.regex.Pattern p = java.util.regex.Pattern.compile(regex)
java.util.regex.Matcher m = p.matcher(filecontent)
File SN = new File("C:/device/resources/serialno.txt")
while(m.find()) {
SN.write m.group(1)
}

If your code doesn't enter the loop it means that there are no matches so you need to amend your regular expression, you can use i.e. Regex101 website for experiments
Given the following content of the testresults.txt file:
SerialNumber" value="foo"
SerialNumber" value="bar"
SerialNumber" value="baz"
your code works fine.
For the time being I can only suggest using match operator to make your code more "groovy"
def source = new File('C:/device/resources/testresults.txt').text
def matches = (source =~ 'SerialNumber" value="(.+?)"')
matches.each { match ->
new File('C:/device/resources/serialno.txt') << match[1] << System.getProperty('line.separator')
}
Demo:
More information: Apache Groovy - Why and How You Should Use It

Related

Unable to read value from location URL using RegEx inside BeanShell Post Processor

I am using JMeter to automate performance test cases. After HTTP request, I have used RegEx Post Extractor to read the response header. This response header return location. Location is project-specific URL. I want to read the value of the state variable from this URL. For this, I have used BeanShell PostProcessor. For example,
location: "http://www.google.com/state=asdas123123123123&query=asdasdas!##"
I am able to read value of response header as http://www.google.com/state=asdas123123123123&query=asdasdas!##" using regular expression extractor
Then, I have added BeanShell PostProcesssor to read state and query.
import java.util.regex.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
try{
//location = "http://www.google.com/state=asdas123123123123&query=asdasdas!##"
String location = vars.get("location");
String pStr = "/state=(\\S+?)&/"";
Pattern patternN = Pattern.compile(pStr);
Matcher matcher = patternN.matcher(pStr);
if (matcher.find()) {
vars.put("variablename_1",matcher.group(0));
}
vars.put("variablename_2",location);
}catch (Exception ex) {
vars.put("variablename_ex",ex);
throw ex;
}
This code is not working. It seems double slash is creating problems.
Since JMeter 3.1 you should be using JDR223 Test Elements and Groovy language for scripting
Groovy provides Find operator which looks like =~
Assuming above 2 points you can refactor your "code" to this one-liner:
vars.put('variablename_1', (vars.get('location') =~ /state=(\w+)&/)[0][1])
Demo:
More information:
Pattern Matching in Strings in Groovy
Apache Groovy - Why and How You Should Use It

Parsing value from the Jmeter string response

I'm trying to get a value of post_data[‘postcode’] on Jmeter. I tried to parse with JSR223 PostProcessor with the below code but looks like my code is not able to find that variable name.
Response:
<script type="text/javascript">
parent.$("#dialog:ui-dialog").dialog("destroy");
parent.$("#dialog-message div").html("");
var url = '';
var post_data = {};
post_data[‘user’] = “value1”;
post_data[‘city’] = “value2”;
post_data[‘postcode’] = “value3”;
post_data[‘country’] = “value3”;
</script>
JSR223 PostProcessor groovy script:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String stringToSearch=prev.getResponseDataAsString();
Pattern p = Pattern.compile("post_data[‘postcode’] = (\\w+)");
Matcher m = p.matcher(stringToSearch);
if (m.find()){
vars.put("postcode", m.group(1));
}
Any help is greatly appreciated.
You need to surround your match group with quotation marks
You need to escape meta characters
Groovy provides match operator out of box so you can simplify your code as:
vars.put('postcode', (prev.getResponseDataAsString() =~ /post_data\[‘postcode’\] = “(\w+)”/)[0][1])
Demo:
More information:
Groovy Regular Expressions - The Definitive Guide
Apache Groovy - Why and How You Should Use It

Jmeter - find with regex and replace part of XML body using groovy

I'm trying to replace part an XML response data with something else.
Here is an example:
?xml version="1.0" encoding="UTF-8"?>
<trustedDevices><trustedDevice><id>1942</id><name>BksQ9LKwWuNOHpn</name></trustedDevice><trustedDevice><id>1944</id><name>6f4srs4PkJk1j36</name></trustedDevice><trustedDevice><id>1943</id><name>7cGYVAlmQoXaVrf</name></trustedDevice></trustedDevices>
I'm trying to get all the <name>(.+?)<\/name> data and replace it with something else (timestamp or random string)
so far, my groovy post processor code looks like this:
String trustedDevices = prev.getResponseDataAsString()
log.info('Response: ' + trustedDevices)
def nameFind = "/<name>(.+?)<\/name>/"
def newTrustedDevices = trustedDevices.replaceAll(nameFind, "test")
log.info('New response: ' + newTrustedDevices)
Unfortunately it seems that replaceAll requires String or Long to work, and won't work with regex.
You regex just need a correct escaping:
def nameFind = "<name>(.+?)<\\/name>"
Replacing values in XML using regular expressions is not the best option as it will be fragile and very sensitive to any markup change.
I would suggest going for Groovy's XML parsing capabilities instead
Example code:
def trustedDevices = new XmlSlurper().parseText(prev.getResponseDataAsString())
trustedDevices.trustedDevice.findAll().each {
it.name = 'test'
}
def newTrustedDevices = new StreamingMarkupBuilder().bind { mkp.yield trustedDevices }.toString()
More information on Groovy scripting in JMeter: Apache Groovy - Why and How You Should Use It

Regex from Python to Kotlin

I have a question about Regular Expression (Regex) and I really newbie in this. I found a tutorial a Regex written in Python to delete the data and replace it with an empty string.
This is the code from Python:
import re
def extract_identity(data, context):
"""Background Cloud Function to be triggered by Pub/Sub.
Args:
data (dict): The dictionary with data specific to this type of event.
context (google.cloud.functions.Context): The Cloud Functions event
metadata.
"""
import base64
import json
import urllib.parse
import urllib.request
if 'data' in data:
strjson = base64.b64decode(data['data']).decode('utf-8')
text = json.loads(strjson)
text = text['data']['results'][0]['description']
lines = text.split("\n")
res = []
for line in lines:
line = re.sub('gol. darah|nik|kewarganegaraan|nama|status perkawinan|berlaku hingga|alamat|agama|tempat/tgl lahir|jenis kelamin|gol darah|rt/rw|kel|desa|kecamatan', '', line, flags=re.IGNORECASE)
line = line.replace(":","").strip()
if line != "":
res.append(line)
p = {
"province": res[0],
"city": res[1],
"id": res[2],
"name": res[3],
"birthdate": res[4],
}
print('Information extracted:{}'.format(p))
In the above function, information extraction is done by removing all e-KTP labels with regular expressions.
This is the sample of e-KTP:
And this is the result after scanning that e-KTP using the python code:
Information extracted:{'province': 'PROVINSI JAWA TIMUR', 'city': 'KABUPATEN BANYUWANGI', 'id': '351024300b730004', 'name': 'TUHAN', 'birthdate': 'BANYUWANGI, 30-06-1973'}
This is the full tutorial from the above code.
And then my question is, can we use Regex in Kotlin to remove the label from the result of e-KTP like in python code? Because I try some logic that I understand it does not remove the label of e-KTP. My code in Kotlin like this:
....
val lines = result.text.split("\n")
val res = mutableListOf<String>()
Log.e("TAG LIST STRING", lines.toString())
for (line in lines) {
Log.e("TAG STRING", line)
line.matches(Regex("gol. darah|nik|kewarganegaraan|nama|status perkawinan|berlaku hingga|alamat|agama|tempat/tgl lahir|jenis kelamin|gol darah|rt/rw|kel|desa|kecamatan"))
line.replace(":","")
if (line != "") {
res.add(line)
}
Log.e("TAG RES", res.toString())
}
Log.e("TAG INSERT", res.toString())
tvProvinsi.text = res[0]
tvKota.text = res[1]
tvNIK.text = res[2]
tvNama.text = res[3]
tvTgl.text = res[4]
....
And this is the result of my code:
TAG LIST STRING: [PROVINSI JAWA BARAP, KABUPATEN TASIKMALAYA, NIK 320625XXXXXXXXXX, BRiEAFAUZEROMARA, Nama, TempatTgiLahir, Jenis keiamir, etc]
TAG INSERT: [PROVINSI JAWA BARAP, KABUPATEN TASIKMALAYA, NIK 320625XXXXXXXXXX, BRiEAFAUZEROMARA, Nama, TempatTgiLahir, Jenis keiamir, etc]
The label still exists, It's possible to remove a label using Regex or something in Kotlin like in Python?
The point is to use kotlin.text.replace with a Regex as the search argument. For example:
text = text.replace(Regex("""<REGEX_PATTERN_HERE>"""), "<REPLACEMENT_STRING_HERE>")
You may use
line = line.replace(Regex("""(?i)gol\. darah|nik|kewarganegaraan|nama|status perkawinan|berlaku hingga|alamat|agama|tempat/tgl lahir|jenis kelamin|gol darah|rt/rw|kel|desa|kecamatan"""), "")
Note that (?i) at the start of the pattern is a quick way to make the whole pattern case insensitive.
Also, when you need to match a . with a regex you need to escape it. Since a backslash can be coded in several ways and people often fail to do it correctly, it is always recommended to define regex patterns within raw string literals, in Kotlin, you may use the triple-double-quoted string literals, i.e. """...""" where each \ is treated as a literal backslash that is used to form regex escapes.

Python Dictionary re

As you can see in code using regular expression script searches for words in txt and puts them to dictionary like this:
set(["['card', 'port']"])
set(["['onu_id', 'remote_id']"])
set(["['card', 'port', 'onu_id']"])
set(["['card', 'port', 'onu_id']"])
set(["['remote_id']"])
set(["['remote_id']"])
set(["['card', 'port', 'onu_id']"])
Problem is that i need to input values to them by hand and remove everything except keys(card,port,onu_id,remote_id)(remove: set(["[' to see everything clearly:
dict{card:1, port:5, onu_id:3, remote_id:16568764}
To look like this and be easy to read.
Here is my code:
import re, string
with open("conf.txt","r") as f:
text = f.readlines()
for line in text:
match = re.findall(r'_\$(\w+)',line)
if match:
dict = {str(match)}
print dict
part of input file:
interface gpon-olt_1/_$card/_$port
onu _$onu_id type ZTE-F660 pw _$remote_id vport-mode gemport
no lock
no shutdown
exit
interface gpon-onu_1/_$card/_$port:\_$onu_id
exit
interface gpon-onu_1/_$card/_$port:\_$onu_id
name ONU-_$remote_id 102211+1
description
vport-mode gemport def-map-type 1:1