I have two values to correlate and I am able to capture them in two parameters successfully. I am taking random values using -1 in match number, but I actually wanted in a way like, let's say my first value randomly take the match number as 7 and I want my second value also should take the same match num as 7.
Please help me how I can simulate this .
Unfortunately, (as you've discovered), JMeter determines the 'random' independently. What you'll need to do is capture each potential value (with a -1) for both of var1 and var2. Then after your Regexes, add a Beanshell Postprocessor that gets a random number n, then picks the nth var1 and var2:
String random_number = Integer(random.nextInt(vars.get("var1_name_matchNr"))).toString;
vars.put("var1_name_chosen",vars.get("var1_name_" + random_number));
vars.put("var2_name_chosen",vars.get("var2_name_" + random_number));
If I understood correctly, you want to extract random regex value, and put it into 2 variables. If so, I would suggest doing something like...
After you get random regex value, add beanshell in which you will paste value you got with regex into the second variable.
So if your variable in regex is "foo1", just add beanshell sampler with:
vars.put("foo2", vars.get("foo1"));
EDIT:
This would be better as Java sampler, but I think it should work in BeanShell sampler as well.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.threads.JMeterContextService;
import java.util.ArrayList;
import java.util.Random;
String previousResponse = JMeterContextService.getContext()
.getPreviousResult().getResponseDataAsString();
String locationLinkRegex = "\"locationId\": (.+?),";
String myLocationId = RegexMethod(previousResponse, locationLinkRegex,
true);
String myLocationLink = RegexMethod(
previousResponse,
"\"locationId\": ".concat(myLocationId).concat(
", \"locationLink\":(.+?))\""), false);
JMeterContextService.getContext().getVariables()
.put("locationId", myLocationId);
JMeterContextService.getContext().getVariables()
.put("locationLink", myLocationLink);
private static String RegexMethod(String response, String regex,
Boolean random) {
Random ran = new Random();
String result = "No matcher!";
ArrayList<String> allMatches = new ArrayList<String>();
allMatches = null;
if (random) {
Matcher m = Pattern.compile(regex, Pattern.UNICODE_CASE).matcher(
response);
while (m.find()) {
allMatches.add(m.group());
}
result = allMatches.get(ran.nextInt(allMatches.size()));
} else {
Matcher m = Pattern.compile(regex, Pattern.UNICODE_CASE).matcher(
response);
m.find();
result = m.group(1);
}
return result;
}
Exception handling needs to be implemented as well...
EDIT2:
And the Regex-method as recursive (returns both values as CSV, and can be use only if locationId is unique):
private static String RegexMethod(String response, String regex) {
Random ran = new Random();
String result = "No matcher!";
List<String> allMatches = new ArrayList<String>();
// Find LocationId:
Matcher m1 = Pattern.compile(regex, Pattern.UNICODE_CASE).matcher(
response);
while (m1.find()) {
allMatches.add(m1.group());
}
result = allMatches.get(ran.nextInt(allMatches.size())).concat(",");
// Find LocationLink and return the CSV string:
return result += RegexMethod(response, "\"locationId\": "
.concat(result.substring(result.length()-1)).concat(", \"locationLink\":(.+?))\""));
}
Related
I'm trying to filter a String list like:
List<String> names = ["NAM", "XYZ", "+QWE (HJB)", "+XYZ (NAM)", "(NAM)"];
While using regex I want to compare each String with a string that contains "NAM" or "HJB" and print every string of names containing the filter string out. So in the end it would print out everything with "NAM" in it (also "+XYZ (NAM)", but without the special chars)
My code looks like this but either way I catch everything ("+QWE (HJB)")
regexp3 = RegExp(r'[a-zA-Z]+');
or Nothing
final regexp2 = RegExp(r'^\+.([a-zA-Z]+) \(([a-zA-Z]+).\).$');
because if I only filter with "NAM" (for example) it gives me an null error.
Complete code.
void main() async {
List<String> names= ["TEX","TOL","+TEX (TOL)","+TOL (TEX)", "(NAM)"];
List<String> filter = ["TEX", "TOL"];
final regexp3 = RegExp(r'[a-zA-Z]+');
for(var e in names){
if(filter.contains(regexp3.firstMatch(e)!.group(0))) {
print(e);
}
}
}
Writing regex patterns is indeed giving us a slight nystagmus. However, it is important to be careful about the regex groups numeration. As far as I understand, you want to get the content of group(1) which is captured by the first parenthesis after \+.
To match the strings correctly I also removed a few . characters from the regex pattern.
Replaced the bang operator (!) with ? and ?? in addition to provide safe default value instead of throwing errors on nulls.
Good luck!
void main() async {
List<String> names= ["TEX","TOL","+TEX (TOL)","+TOL (TEX)", "(NAM)"];
List<String> filter = ["TEX", "TOL"];
final regexp3 = RegExp(r'^\+([a-zA-Z]+) \(([a-zA-Z]+)\)$');
for(var e in names){
var regroup = regexp3.firstMatch(e)?.group(1);
if(filter.contains(regroup)) {
print(e + '\t\t' + (regroup ?? ''));
}
}
}
I am doing a list.where filter:
String needleTemp = '';
final String hayStack =
[itemCode, itemDesc, itemCodeAlt, itemDescAlt, itemGroup].join(' ');
for (final k in query.split(" ")) {
needleTemp = '$needleTemp(?=.*\\Q$k\\E)';
}
var re = RegExp(needleTemp);
return re.hasMatch(hayStack);
I printed the output for needleTemp and it looks the same as on my regex101 example:
in dart it prints (?=.*\Qa/a\E)(?=.*\Qpatro\E)
basically the same, but nothing matches, not even a simple letter.
Is dart regex different or do I need another syntax?
edit:
Simple example to test in DartPad:
void main() {
print("(?=.*\\Qpatrol\\E)");
var re = RegExp("(?=.*\\Q2020\\E)");
print(re.hasMatch('A/A PATROL 2020'));
}
still returns false
Found the solution:
I just need to remove \Q and \E then RegExp.escape(text_to_escape) inside the needle.
I have a string which contains something like this number: -7-972/516/57.15
. Expression must return the number of digits and filter by first number. In result i want to see: 79725165715
. I wrote this expression ^(\D*)+7+(\D*(?:\d\D*){10})$, but that expression got problem "Catastrophic Backtracking"(freezes on execution) with long strings like: bt.rfznascvd#rcs.ru,e.zovtrnko#lkn.ru
I write a new one and that works: \D*7(\d\D*){10}
You just have to use \d. Using of Matches will give you all matches in pattern from considered line. Count of it wwill give you count of matches. And for concatanate them to string I created small extension method.
For testing your regexes I can advice regexlib.
namespace CSharpTest
{
using System.Text;
using System.Text.RegularExpressions;
public static class Program
{
static void Main(string[] args)
{
string input = #"number: -7-972/516/57.15";
var regex = new Regex(#"\d");
var matches = regex.Matches(input);
var countOfNumbers = matches.Count;
var number = matches.ToNumber();
}
public static string ToNumber(this MatchCollection matches)
{
var result = new StringBuilder();
foreach (Match match in matches)
result.Append(match.Value);
return result.ToString();
}
}
}
I tried this solution to test if a string in substring:
val reg = ".*\\[CS_RES\\].*".r
reg.findAllIn(my_DataFrame).length
But it is not working because I can't apply findAllIn to a Dataframe.
I tried this second solution, I converted my DataFrame to RDD:
val rows: RDD[Row] = myDataFrame.rdd
val processedRDD = rows.map{
str =>
val patternReg = ".*\\[CS_RES\\].*".r
val result = patternReg.findAllIn(str).length
(str, result)
}
it displays an error:
<console>:69: error: type mismatch;
found : org.apache.spark.sql.Row
required: CharSequence
val result = patternReg.findAllIn(str).length
How can I apply a Regex on a DataFrame scala in the first solution to compute the number of the lines that contain the string [CS_RES]
or if someone have a solution for the second solution ?
You can use regexp_extract function to filter and count the lines. For example:
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
private val session: SparkSession = ...
import session.implicits._
val myDataFrame = Seq(
(1L, "abc"),
(2L, "def"),
(3L, "a[CS_RES]b"),
(4L, "adg")
).toDF("id", "text")
val resultRegex = myDataFrame.where(regexp_extract($"text", "\\[CS_RES\\]", 0).notEqual("")).count()
println(resultRegex) // outputs 1
The idea is: if the first group (i=0) returned by regexp_extract is not an empty string, the substring is found. The invocation of count() returns the total number of those strings.
But if you need to find only exact matches of substrings, the solution can be simplified by using locate function:
val resultLocate = myDataFrame.where(locate("[CS_RES]", $"text") > 0).count()
println(resultLocate) // outputs 1
import org.apache.spark.sql.functions.udf
val reg = ".*\\[CS_RES\\].*".r
val contains=udf((s:String)=>reg.findAllIn(s).length >0)
val cnt = df.select($"summary").filter(contains($"summary")).count()
Is there a way to count the number of replacements a Regex.Replace call makes?
E.g. for Regex.Replace("aaa", "a", "b"); I want to get the number 3 out (result is "bbb"); for Regex.Replace("aaa", "(?<test>aa?)", "${test}b"); I want to get the number 2 out (result is "aabab").
Ways I can think to do this:
Use a MatchEvaluator that increments a captured variable, doing the replacement manually
Get a MatchCollection and iterate it, doing the replacement manually and keeping a count
Search first and get a MatchCollection, get the count from that, then do a separate replace
Methods 1 and 2 require manual parsing of $ replacements, method 3 requires regex matching the string twice. Is there a better way.
Thanks to both Chevex and Guffa. I started looking for a better way to get the results and found that there is a Result method on the Match class that does the substitution. That's the missing piece of the jigsaw. Example code below:
using System.Text.RegularExpressions;
namespace regexrep
{
class Program
{
static int Main(string[] args)
{
string fileText = System.IO.File.ReadAllText(args[0]);
int matchCount = 0;
string newText = Regex.Replace(fileText, args[1],
(match) =>
{
matchCount++;
return match.Result(args[2]);
});
System.IO.File.WriteAllText(args[0], newText);
return matchCount;
}
}
}
With a file test.txt containing aaa, the command line regexrep test.txt "(?<test>aa?)" ${test}b will set %errorlevel% to 2 and change the text to aabab.
You can use a MatchEvaluator that runs for each replacement, that way you can count how many times it occurs:
int cnt = 0;
string result = Regex.Replace("aaa", "a", m => {
cnt++;
return "b";
});
The second case is trickier as you have to produce the same result as the replacement pattern would:
int cnt = 0;
string result = Regex.Replace("aaa", "(?<test>aa?)", m => {
cnt++;
return m.Groups["test"] + "b";
});
This should do it.
int count = 0;
string text = Regex.Replace(text,
#"(((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#])?)", //Example expression. This one captures URLs.
match =>
{
string replacementValue = String.Format("<a href='{0}'>{0}</a>", match.Value);
count++;
return replacementValue;
});
I am not on my dev computer so I can't do it right now, but I am going to experiment later and see if there is a way to do this with lambda expressions instead of declaring the method IncrementCount() just to increment an int.
EDIT modified to use a lambda expression instead of declaring another method.
EDIT2 If you don't know the pattern in advance, you can still get all the groupings (The $ groups you refer to) within the match object as they are included as a GroupCollection. Like so:
int count = 0;
string text = Regex.Replace(text,
#"(((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#])?)", //Example expression. This one captures URLs.
match =>
{
string replacementValue = String.Format("<a href='{0}'>{0}</a>", match.Value);
count++;
foreach (Group g in match.Groups)
{
g.Value; //Do stuff with g.Value
}
return replacementValue;
});