Pattern for ulr (key=value&key=value) Java regex - java

Want to know how to write the correct pattern regex of my url to match this :
key=value .
2 pairs of key=value are Separated by « & » .
Remove key if value is empty or null
Thanks

If you want to remove empty parameters from your query string, you can use this regex \w+=[^&]+ to match only key value pairs whose value part is non-empty. For e.g. if you have following string,
key1=value1&key2=value2&key3=&key4=value4
Then match only URLs using above regex and filter out rest. This Java code should help you,
String s = "key1=value1&key2=value2&key3=&key4=value4";
Pattern p = Pattern.compile("\\w+=[^&]+");
Matcher m = p.matcher(s);
StringBuilder sb = new StringBuilder();
while(m.find()) {
sb.append(m.group()).append("&");
}
System.out.println(sb.substring(0,sb.length()-1));
Prints this which has key3 value removed as it was empty,
key1=value1&key2=value2&key4=value4
Using Java8 streams, you can use this one liner code to achieve,
String s = "key1=value1&key2=value2&key3=&key4=value4";
String cleaned = Arrays.stream(s.split("&")).filter(x -> Pattern.matches("\\w+=[^&]+", x)).collect(Collectors.joining("&"));
System.out.println(cleaned);
Prints,
key1=value1&key2=value2&key4=value4

Related

Converting string of lists to list of string in java

I am getting a value as list of string in string format like this: "["a", "b"]". I would like to convert them to a list of strings. I can do this by stripping the leading and trailing braces and then splitting on comma. But here the problem is that I may receive the same value as single string also "a" that too I want to convert to a list of strings. So is there any way to generalize this.
One possible solution is to use Regex.
Your expression can look like this: "(.+?)"
.+? matches any character (except for line terminators)
+? Quantifier - Matches between one and unlimited times, as few times as possible, expanding as needed.
String tokens = "[\"a\", \"b,c\", \"test\"]";
String pattern = "\"(.+?)\"";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(tokens);
List<String> tokenList = new ArrayList<String>();
while (m.find()) {
tokenList.add(m.group());
}
System.out.println(tokenList);
you can generalize the following:
String str = "\"[\"a\",\"b\"]\"";
String[] splitStrs = str.split("\"",7);
System.out.println(splitStrs[0]+" "+splitStrs[1]+" "+splitStrs[2]+" "+splitStrs[3]+" "+splitStrs[4]+" "+splitStrs[5]+" "+splitStrs[6]);
My output
[ a , b ]

Replace the opening and closing string, while keeping the enclosed value?

String value="==Hello==";
For the above string, I have to replace the "==" tags as <Heading>Hello</Heading>. I have tried doing it like this:
value = value.replaceAll("(?s)\\=\\=.","<heading>");
value = value.replaceAll(".\\=\\=(?s)","</heading>");
However, my original dataset is huge, with lots of strings like this to be replaced. Can the above be performed in a single statement, giving preference to performance?
The regex should not affect strings of form, ===<value>===, where value is any string of characters[a-z,A-Z].
To avoid iterating over string many times to first replace ===abc=== and then ==def== we can iterate over it once and thanks to Matehr#appendReplacement and Matcher#appendTail dynamically decide how to replace found match (based on amount of =).
Regex which can search find both described cases can look like: (={2,3})([a-z]+)\1 but to make it more usable lets use named groups (?<name>subregex) and also instead of [a-z] use more general [^=]+.
This will give us
Pattern p = Pattern.compile("(?<eqAmount>={2,3})(?<value>[^=]*)\\k<eqAmount>");
Group named eqAmount will hold == or ===. \\k<eqAmount> is backreference to that group, which means regex expects to find it also == or === depending on what eqAmount already holds.
Now we need some mapping between == or === and replacements. To hold such mapping we can use
Map<String,String> replacements = new HashMap<>();
replacements.put("===", "<subheading>${value}</subheading>");
replacements.put("==", "<heading>${value}</heading>");
${value} is reference to capturing group named value - here (?<value>[^=]*) so it will hold text between both == or ===.
Now lets see how it works:
String input = "===foo=== ==bar== ==baz== ===bam===";
Map<String, String> replacements = new HashMap<>();
replacements.put("===", "<subheading>${value}</subheading>");
replacements.put("==", "<heading>${value}</heading>");
Pattern p = Pattern.compile("(?<eqAmount>={2,3})(?<value>[^=]*)\\k<eqAmount>");
StringBuffer sb = new StringBuffer();
Matcher m = p.matcher(input);
while (m.find()) {
m.appendReplacement(sb, replacements.get(m.group("eqAmount")));
}
m.appendTail(sb);
String result = sb.toString();
System.out.println(result);
Output: <subheading>foo</subheading> <heading>bar</heading> <heading>baz</heading> <subheading>bam</subheading>
Try this:
public static void main(final String[] args) {
String value = "===Hello===";
value = value.replaceAll("===([^=]+)===", "<Heading>$1</Heading>");
System.out.println(value);
}

Android Java, replace each letter in a text [duplicate]

I have some strings with equations in the following format ((a+b)/(c+(d*e))).
I also have a text file that contains the names of each variable, e.g.:
a velocity
b distance
c time
etc...
What would be the best way for me to write code so that it plugs in velocity everywhere a occurs, and distance for b, and so on?
Don't use String#replaceAll in this case if there is slight chance part you will replace your string contains substring that you will want to replace later, like "distance" contains a and if you will want to replace a later with "velocity" you will end up with "disvelocityance".
It can be same problem as if you would like to replace A with B and B with A. For this kind of text manipulation you can use appendReplacement and appendTail from Matcher class. Here is example
String input = "((a+b)/(c+(d*e)))";
Map<String, String> replacementsMap = new HashMap<>();
replacementsMap.put("a", "velocity");
replacementsMap.put("b", "distance");
replacementsMap.put("c", "time");
StringBuffer sb = new StringBuffer();
Pattern p = Pattern.compile("\\b(a|b|c)\\b");
Matcher m = p.matcher(input);
while (m.find())
m.appendReplacement(sb, replacementsMap.get(m.group()));
m.appendTail(sb);
System.out.println(sb);
Output:
((velocity+distance)/(time+(d*e)))
This code will try to find each occurrence of a or b or c which isn't part of some word (it doesn't have any character before or after it - done with help of \b which represents word boundaries). appendReplacement is method which will append to StringBuffer text from last match (or from beginning if it is first match) but will replace found match with new word (I get replacement from Map). appendTail will put to StringBuilder text after last match.
Also to make this code more dynamic, regex should be generated automatically based on keys used in Map. You can use this code to do it
StringBuilder regexBuilder = new StringBuilder("\\b(");
for (String word:replacementsMap.keySet())
regexBuilder.append(Pattern.quote(word)).append('|');
regexBuilder.deleteCharAt(regexBuilder.length()-1);//lets remove last "|"
regexBuilder.append(")\\b");
String regex = regexBuilder.toString();
I'd make a hashMap mapping the variable names to the descriptions, then iterate through all the characters in the string and replace each occurrance of a recognised key with it's mapping.
I would use a StringBuilder to build up the new string.
Using a hashmap and iterating over the string as A Boschman suggested is one good solution.
Another solution would be to do what others have suggested and do a .replaceAll(); however, you would want to use a regular expression to specify that only the words matching the whole variable name and not a substring are replaced. A regex using word boundary '\b' matching will provide this solution.
String variable = "a";
String newVariable = "velocity";
str.replaceAll("\\b" + variable + "\\b", newVariable);
See http://docs.oracle.com/javase/tutorial/essential/regex/bounds.html
For string str, use the replaceAll() function:
str = str.toUpperCase(); //Prevent substitutions of characters in the middle of a word
str = str.replaceAll("A", "velocity");
str = str.replaceAll("B", "distance");
//etc.

how to filter string but keep some tags

how can i filter string?
String[] filterTags={<A>,<BC>,<A,<B};
filterTags can contains more values it can contains some string, numeric or anything can grow dyanmically
String name="<A><ABC><B><B"
what i want is remove values from filterTags array but keep <ABC> as it is from the name(String)
if (name.contains(filterTags[i])and ???)
i need just a simple check which will remove the filterTags values if contains in name (String) but keep as it is
thank you in advanced
Well, you can do this with a regex:
String filtered = name.replaceAll("(<A>|<BC>|<A|<B)", "");
// filtered == "<ABC>"
The problem is now to create that regex String. You can hardcode it, since it looks like that's what you're doing with the array anyways, or you could do something like this:
StringBuilder sb = new StringBuilder("(");
for (String token : filterTags) {
sb.append(token);
sb.append('|');
}
sb.deleteCharAt(sb.length() - 1); // Remove the last "|"
sb.append(')');
String regex = sb.toString();
Note that this will only work if your filter tags don't contain any regex special characters
Simply you Can do this with regex
String name = "<A><ABC><c<B<s";
pattern = Pattern.compile(".*(<ABC>).*");
matcher = pattern.matcher(name);
matcher.matches();
System.out.println(matcher.group(1)); // prints <ABC>

extract substring attributes and values from main string in JAVA

I have the following String:
\018attribute1=value1\028attribute2=value2\033attribute3=value3
Note: the "\0xx" is a hard string no special character include and "\0xx" is random. I get this string from an api and it contains the "\" character.
I want to extract attribute names and attribute values
how to do it?
You need to escape the \ character twice. Once for Java, and once for regex. This turns it into \\\\. Then you can use Pattern and Matcher to build a map of your values:
Pattern p = Pattern.compile("\\\\0..([^=]+)=([^\\\\]*)");
Matcher matcher = p.matcher("\\018attribute1=value1\\028attribute2=value2\\033attribute3=value3");
Map<String, String> attributes = new HashMap<String, String>();
while (matcher.find()) {
attributes.put(matcher.group(1), matcher.group(2));
}
Something like so worked for me:
String str = "\\018attribute1=value1\\028attribute2=value2\\033attribute3=value3";
Pattern p = Pattern.compile("0\\d{2}(.*?)=(.*?)(\\\\|$)");
Matcher m = p.matcher(str);
while(m.find())
{
System.out.println(m.group(1));
System.out.println(m.group(2));
System.out.println("-------");
}
It yielded:
attribute1
value1
-------
attribute2
value2
-------
attribute3
value3
The regex assumes that the pattern you need to match will always start with a back slash followed by 2 digits (\0xx). It will then extract the first substring until it hits the equals sign. Once it matches the equals sign, it will keep matching until it either hits another slash or else the end of the string.
If you will not have the three digits, you can either substitute it with something along the lines of \0\w{2} this will match a zero followed by anything which is a letter, number or underscore.

Categories