I want to replace querystring value but it's creating some problems:
Problem 1: Its Removing the "&" symbol after replacing
String queryString = "?pid=1&name=Dell&cid=25";
String nQueryString=queryString.replaceAll("(?<=[?&;])pid=.*?($|[&;])","pid=23");
System.out.println(nQueryString);
output of above example
?pid=23name=Dell&cid=25
you can see its removed the "&" after pid
Problem 2: Its not working if I removed the "?" symbol from the queryString variable.
String queryString = "pid=1&name=Dell&cid=25";
String nQueryString=queryString.replaceAll("(?<=[?&;])pid=.*?($|[&;])","pid=23");
System.out.println(nQueryString);
output of above example
?pid=1&name=Dell&cid=25
We can say the regex is not working, So anyone can suggest me better regex which completely fulfill my requirements.
queryString.replaceAll("(?<=[?&;])pid=.*?(?=[&;])", "pid=23")
Difference is that I'm using a positive-lookahead: (?=[&;]), which is zero-length, making it atomic, and is not actually included in the replacement via replaceAll(), just like your original positive-lookbehind is not replaced.
Alternatively, we can match until a & or ; is found, but not included in the replacement, ie:
queryString.replaceAll("(?<=[?&;])pid=[^&;]*", "pid=23")
[^&;] : ^ negates the following: &;, so [^&;]* will match until a ; or & is encountered.
Yours does not work because ($|[&;]) is a non-atomic group, specifically a capturing group, and thus is included in the replacement. NB: a non-capturing group (?:$|[&;]) would also fail here.
To your final note, you're using a positive look-behind for ?, &, and ;, so by removing the ?, it will no longer match, which makes sense.
Use this regex instead:
String nQueryString = queryString.replaceAll("(?<=[?&;])pid=[^&]*", "pid=23");
//=> ?pid=23&name=Dell&cid=25
Here [^&]* is called negation matching pattern, that will match query string value until & is found OR else end of string is found thus leaving rest of the query string un-effected.
Related
I am new to regEx. I need to validate email using java. I have created regEx for email validation by hardcoding the domain name. But the domain name should be dynamic. I have passed the domain name as a parameter. But I don't know how to pass parameter in regEx.
But I tried this code, then I got the error "java.util.regex.PatternSyntaxException: Illegal repetition near index 12". I have followed some answers but it doesn't help for me. From those answers I understood about repetition quantifier. Can you tell me what I am missing here and how to solve this issue?
public static boolean validateEmail(String email, String domainName) {
pattern = Pattern.compile("^([\\w-\\.]+)# {"+ domainName +"}" , Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher(email);
return matcher.matches();
}
{ and } have meaning in regex, namely for specifying how often the character before it can repeat. E.g. a{5} matches aaaaa.
If you want to use curly braces in regex, you should escape them like \\{ and \\}.
But that's not what you need for passing this as a parameter — it will just be literal text at that point. If you want to only match that literal domain, you could do Pattern.compile("^([\\w-\\.]+)#" + domainName, Pattern.CASE_INSENSITIVE).
I am facing an issue with the String.replaceFirst method.
I have the following String :
String content = "select * from queries
where update_date >= to_timestamp('#date|Date debut|dd/MM/yyyy# 00:00:00','DD/MM/YYYY HH24:MI:SS')
and update_date <= to_timestamp('#date|Date fin|dd/MM/yyyy# 23:59:59','DD/MM/YYYY HH24:MI:SS')";
(The two expressions between '#' are dynamically defined).
And I have 2 dates too :
String begin = "28/05/2018";
String end = "29/05/2018";
Then I would to replace the first expression with begin, and the second with end.
I use :
content = content.replaceFirst("#(date)\\|(.*)\\|(.*)#", begin);
content = content.replaceFirst("#(date)\\|(.*)\\|(.*)#", end);
Although, replaceFirst takes the last '#' of entire String and I am obtaining:
select * from queries where update_date >= to_timestamp('28/05/2018 23:59:59','DD/MM/YYYY HH24:MI:SS');
I understand the error but I ask you to help me to find a solution.
Thank you a lot ! Axel.
If looking for a generic regex for both replacements as your question's code seems to want, this is how to make it work:
the regex for .* that captures all characters is greedy by default, it means that it will try to capture as many characters as it can. This is why your first replacement replaces all.
You can use the lazy quantifier ? to precise that you want to capture the less characters possible instead of the most.
try:
#(date)\|(.*?)\|(.*?)#
(or escaped version for your code: "#(date)\\|(.*?)\\|(.*?)#")
see regex in regex101
When reading your question, I was not sure whether the text between #s (here I mean "date|Date debut|dd/MM/yyyy" and "date|Date fin|dd/MM/yyyy") were dynamically defined or if you were just explaining that you wanted to dynamically replace the fix contents above with your dynamically defined dates.
So I will give you two answers (and both should work).
If the text is fix:
#date\|Date debut\|dd/MM/yyyy# - for the first range
#date\|Date fin\|dd/MM/yyyy# - for the second range
If the text between # is not fix:
#[^#]*#
The regex above means find a range of chars that start with a #, than contains any chars except a #, this is what [^#] means, 0 or several times (the *) and ends with a #
I hope it helps!
Try this:
String content = "select * from queries " +
"where update_date >= to_timestamp('#date|Date debut|dd/MM/yyyy# 00:00:00','DD/MM/YYYY HH24:MI:SS') " +
"and update_date <= to_timestamp('#date|Date fin|dd/MM/yyyy# 23:59:59','DD/MM/YYYY HH24:MI:SS') ;";
String begin = "28/05/2018";
String end = "29/05/2018";
content = content.replaceFirst( "#date\\|[^\\|]*\\|[^#]*#", begin );
content = content.replaceFirst( "#date\\|[^\\|]*\\|[^#]*#", end );
System.out.println( content );
Here we don't need to use the () and we are matching until our character like | or # matched.
I receive a user input keyword and want to use it to search my database. I built a query that looks something like this:
db.execute("MATCH (n:User) WHERE n.firstname CONTAINS {keyword} OR n.lastname CONTAINS {keyword} RETURN n.username", params);
But this isn't case sensitive, so I thought of manually building the expression and using regular expressions, sort of as follows:
db.execute("MATCH (n:User) WHERE n.firstname =~ '(?i).*" + keyword + ".*' OR n.lastname =~ '(?i).*" + keyword + ".*' RETURN n.username");
I'm looking either for a function for escaping the regex or a better solution for making the query case-insensitive. Any ideas?
I would suggest storing the properties as all lowercase (or uppercase) and then using the Cypher lower() function to convert user input to lowercase for comparison.
Add lowercase name properties
MATCH (n:User)
SET n.lowerFirstName = lower(n.firstname),
n.lowerLastName = lower(n.lastname)
Find lower case matches based on user input
db.execute("MATCH (n:User) WHERE n.lowerFirstName CONTAINS lower({keyword}) OR n.lowerLastName CONTAINS lower({keyword}) RETURN n.username", params);
I've a regex that correctly captures values from the result of a string.
regex is look like;
intGetHatSaatRenk_v22=anyType{SiraNo=(.*?); HatKodu=(.*?) ; GunTipi=(.*?); Gidis=(.*?); ? };
But the problem is the source is like;
intGetHatSaatRenk_v22=anyType{SiraNo=54; HatKodu=502 ; GunTipi=C; Gidis=12:00; RenkGidis=0000FF; };
intGetHatSaatRenk_v22=anyType{SiraNo=55; HatKodu=502 ; GunTipi=C; Gidis=12:07; }; intGetHatSaatRenk_v22=anyType{SiraNo=56; HatKodu=502 ; GunTipi=C; Gidis=12:14; };
as you can see there is an optional field that named RenkGidis, how can i get the value from RenkGidis if it's not null?
with the regex code that i wrote above, i can get if RenkGidis exists in group(4) like 12:00; RenkGidis=0000FF but group(4) must be only 12:00.
I hope that I could explain my problem.
Might want to make the last group optional:
intGetHatSaatRenk_v22=anyType\{SiraNo=([^;\s]*);\s+HatKodu=([^;\s]*)\s*;\s+GunTipi=([^;\s]*);\s+Gidis=([^;\s]*);(?:\s+RenkGidis=([^;\s]*);)?
As a Java string:
"intGetHatSaatRenk_v22=anyType\\{SiraNo=([^;\\s]*);\\s+HatKodu=([^;\\s]*)\\s*;\\s+GunTipi=([^;\\s]*);\\s+Gidis=([^;\\s]*);(?:\\s+RenkGidis=([^;\\s]*);)?"
At the last group ( ?: prevents the group to be captured into output. ( inside ) catpured as usual.
Also changed .*? to [^;\s]* (negation of [;\s] -> any characters, that are no white-space or ;)
As Alan mentioned in the comments, for not getting a null match for the optional part, e.g. just make RenkGidis optional and wrap the value in an alternation with nothing: ([^;\s]*;|)
intGetHatSaatRenk_v22=anyType\{SiraNo=([^;\s]*);\s+HatKodu=([^;\s]*)\s*;\s+GunTipi=([^;\s]*);\s+Gidis=([^;\s]*);(?:\s+RenkGidis=)?([^;\s]*|)
As a Java string:
"intGetHatSaatRenk_v22=anyType\\{SiraNo=([^;\\s]*);\\s+HatKodu=([^;\\s]*)\\s*;\\s+GunTipi=([^;\\s]*);\\s+Gidis=([^;\\s]*);(?:\\s+RenkGidis=)?([^;\\s]*|)"
The regex could look like this
intGetHatSaatRenk_v22=anyType\{SiraNo=(.*?); HatKodu=(.*?) ; GunTipi=(.*?); Gidis=(.*?);( RenkGidis=.*?;\s*|\s*)\};
Group 5 will then be either " RenkGidis=0000FF;" or " ". You can then use a second regex to get 0000FF.
I am doing some string replace in SQL on the fly.
MySQLString = " a.account=b.account ";
MySQLString = " a.accountnum=b.accountnum ";
Now if I do this
MySQLString.replaceAll("account", "account_enc");
the result will be
a.account_enc=b.account_enc
(This is good)
But look at 2nd result
a.account_enc_num=a.account_enc_num
(This is not good it should be a.accountnum_enc=b.accountnum_enc)
Please advise how can I achieve what I want with Java String Replace.
Many Thanks.
From your comment:
Is there anyway to tell in Regex only replace a.account=b.account or a.accountnum=b.accountnum. I do not want accountname to be replace with _enc
If I understand correctly you want to add _enc part only to account or accountnum. To do this you can use
MySQLString = MySQLString.replaceAll("\\baccount(num)?\\b", "$0_enc");
(num)? mean that num is optional so regex will accept account or accountnum
\\b at start mean that there can be no letters, numbers or "_" before account so it wont accept (affect) something like myaccount, or my_account.
\\b at the end will prevent other letters, numbers or "_" after account or accountnum.
It's hard to extrapolate from so few examples, but maybe what you want is:
MySQLString = MySQLString.replaceAll("account\\w*", "$0_enc");
which will append _enc to any sequence of letters, digits, and underscores that starts with account.
try
String s = " a.accountnum=b.accountnum ".replaceAll("(account[^ =]*)", "$1_enc");
it means replace any sequence characters which are not ' ' or '=' which starts the word "account" with the sequence found + "_enc".
$1 is a reference to group 1 in regex; group 1 is the expression in parenthesis (account[^ =]+), i.e. our sequence
See http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html for details