I have following 2 urls:
https://docs.google.com/a/abc.com/spreadsheet/ccc?key=0Aj9Oa8x5fqsL678FNhOUF0ZEN5b25iVVZNdjdUQm9mM1E&usp=drive_web#gid=0
https://docs.google.com/a/abc.com/file/d/0Aj9Oa8x5fqsL678FNhOUF0ZEN5b25iVVZNdjdUQm9mM1E/edit
I am using following regex:
Pattern.compile(".*key=|/d/(.[^&/])")
as a result of it I want that the matcher.group() returns both urls upto fileId(0Aj9Oa8x5fqsL678FNhOUF0ZEN5b25iVVZNdjdUQm9mM1E) part and matcher.group(1) returns the fileId.
but I am not getting these results.
you fell victim to the precedence rules in regex expressions and forgot the repetition specifier for your character class. try
Pattern.compile("(key=|/d/)([^&/]+)")
your result will be in $2.
If you don't need to use a regex, then use URI:
private static final Pattern PARAM_SEPARATOR = Pattern.compile("&");
private static final Pattern PATH_MATCHER = Pattern.compile("/file/d/([^/]+)");
// In query parameter...
public static String getKeyQueryParamFromURI(final String input)
{
final URI uri = URI.create(input);
final String params = uri.getQuery();
if (params == null)
return null;
for (final String param: PARAM_SEPARATOR.split(input))
if (param.startsWith("key="))
return param.substring(4);
return null;
}
// In path...
public static String getPathMatcherFromURI(final String input)
{
final URI uri = URI.create(input);
final String path = uri.getPath();
if (path == null)
return null;
final Matcher m = PATH_MATCHER.matcher(input);
return m.find() ? m.group(1) : null;
}
Note that unlike a regex, you will receive the result unescaped. If for instance the URI reads key=a%20b, this will return you "a b"!
If you insist on using a regex (why?), then do that instead for the query parameter:
private static final Pattern PATTERN = Pattern.compile("(?<=[?&])key=([^&]+)");
public static String getKeyQueryParamFromURI(final String input)
{
final Matcher m = PATTERN.matcher(input);
return m.find() ? m.group(1) : null;
}
But you'll have to unescape the parameter value yourself...
It's prefer for two different regex pattern to split the regex statement and not use |(OR).
With using different pattern you will have the first capture group the result you wanted.
Pattern1:
.*key=(.*)=.*
Pattern2:
.*\/file\/?\/(.*)\/.*
Related
I should check if that string is valid. So i can i check UUID parts with this regex expression
private String UUID = "([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})"
private String url = "customers/00000000-0000-0000-0000-000000000111/areas/00000000-0000-0000-0000-000000000222/orders/00000000-0000-0000-0000-000000000555/invoices/00000000-0000-0000-0000-000000000777/employees/2018-10-31T00:27:31.205+0000.jpg"
like this
Pattern JPG_PATTERN = Pattern.compile(
String.format("customers/%s/areas/%<s/orders/%<s/invoices/%<s/employees/", UUID));
Matcher m = JPG_PATTERN.matcher(url);
if (m.find()) {
System.out.println("found);
}
But when i add another regex to check last part of the string. It doesn't work.
private String EXTENSION = "(?:mov|jpg)";
Pattern JPG_PATTERN = Pattern.compile(
String.format("customers/%s/areas/%<s/orders/%<s/invoices/%<s/employees/%s", UUID, EXTENSION));
Matcher m = JPG_PATTERN.matcher(url);
if (m.find()) {
System.out.println("found);
}
How can use these two apart regex expression and check if the string is valid?
Your regex does not match filename: 2018-10-31T00:27:31.205+0000.
Change extension regex to String EXTENSION = ".+(?:mov|jpg)";
And change find to matches, otherwise .jpg1 is considered valid. Here is full the code:
private static String UUID = "([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})";
private static String url = "customers/00000000-0000-0000-0000-000000000111/areas/00000000-0000-0000-0000-000000000222/orders/00000000-0000-0000-0000-000000000555/invoices/00000000-0000-0000-0000-000000000777/employees/2018-10-31T00:27:31.205+0000.jpg";
private static String EXTENSION = ".+(?:mov|jpg)";
public static void main(String[] args) {
Pattern JPG_PATTERN = Pattern.compile(String.format("customers/%s/areas/%<s/orders/%<s/invoices/%<s/employees/%s", UUID, EXTENSION));
Matcher m = JPG_PATTERN.matcher(url);
if (m.matches()) {
System.out.println("found");
} else {
System.out.println("not found");
}
}
Here is a fixed version of your code. The blocker I saw on your end seemed to be a misunderstanding of how String#format works. Because you are trying to bind more than one placeholder, I suggest just using %s everywhere and then specifying each string explicitly. Note that the pattern you want to use for the final path component for the extension is slightly different than what you suggested.
String UUID = "([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})";
String EXTENSION = ".*(?:mov|jpg)$";
String pattern = String.format("^customers/%s/areas/%s/orders/%s/invoices/%s/employees/%s", UUID, UUID, UUID, UUID, EXTENSION);
System.out.println(pattern);
^customers/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/areas/
([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/orders/
([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/invoices/
([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/employees/.*(?:mov|jpg)$
Follow the link below for a running regex demo which shows that the above pattern matched your test URL.
Demo
I'm using regex to replace placeholders in a template file.
I have this method:
public static String processTemplate(String template, Map<String, String> attributes) {
Matcher m = PLACEHOLDER_PATTERN.matcher(template);
String message = template;
boolean matches = m.matches();
if (matches) {
for (int i = 1; i < m.groupCount() + 1; i++) {
message = message.replaceAll(m.group(i), attributes.get(m.group(i)));
}
}
return message;
}
with this pattern:
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("(\\$\\{.*?})");
But this test fails:
#Test
public void templates() {
Map<String, String> attributes = new HashMap<>();
attributes.put("${wobble}", "wobble");
String result = processTemplate("wibble ${wobble}", attributes);
assertEquals("wibble wobble", result);
}
And I don't know why. It seems that the 'match' is returning false.
This is how you can process your regex:
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{.*?}");
public static String processTemplate(String template, Map<String, String> attributes) {
Matcher m = PLACEHOLDER_PATTERN.matcher(template);
StringBuffer sb = new StringBuffer();
while (m.find()) {
if (attributes.containsKey(m.group()))
m.appendReplacement(sb, attributes.get(m.group()));
}
m.appendTail(sb);
return sb.toString();
}
Then call it as:
Map<String, String> attributes = new HashMap<>();
attributes.put("${wobble}", "wobble");
String result = processTemplate("wibble ${wobble}", attributes);
//=> "wibble wobble"
Changes are:
Use matcher.find() instead matcher.matches()
Use matcher.appendReplacement() to append each replacement into a buffer
Finally call matcher.appendTail() to append remaining text
The problem is that you are using Matcher.matches() which, as the docs say:
Attempts to match the entire region against the pattern.
So when you pass in "wibble ${wobble}" the match fails because the "wibble " bit isn't accounted for in your regex.
Instead of Matcher.matches() you should use Matcher.find() which will find the next partial match.
I have the following code that uses a specific string and uses the matcher and pattern to draw a link, I also have a method that returns the html code as a string, my problem is that I dont know how to call it so that when the following method runs it uses the dynamic string instead of a static one, I tried using the dynamic string name inside the search but it gave me an error saying that it cannot be compiled since im trying to use a dynamic string instead of a static one, any hints or help would be appreciated, if you need any of my other classes and or methods feel free to ask.
String stringToSearch = "<a>www.google.com</a> ";
Pattern p = Pattern.compile("<a>(\\S+)</a>");
Matcher m = p.matcher(stringToSearch);
if (m.find())
{
String codeGroup = m.group(1);
System.out.format("'%s'\n", codeGroup);
}
}
}
This isn't really a 'design-patterns' question, it is more to do with just knowing how to pass arguments properly into methods.
The Pattern.compile(String) method takes a string as input. That string doesn't have to be a constant. You can pass that string in as a parameter, I've even put it into a 'helper' method to demonstrate that.
public public void someMethod(){
String stringToSearch = "<a>www.google.com</a> ";
String matchPattern = "<a>(\\S+)</a>";
if (doesMatch(matchPattern,stringToSearch)){
String codeGroup = m.group(1);
System.out.format("'%s'\n", codeGroup);
}
}
public static boolean doesMatch(String pattern, String stringToSearch){
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(stringToSearch);
return m.find();
}
to show you what I think you mean...
{
// code...
String stringToSearch = getContent(); //might have parameters here or not
String matchPattern = "<a>(\\S+)</a>";
if (doesMatch(matchPattern,stringToSearch)){
String codeGroup = m.group(1);
System.out.format("'%s'\n", codeGroup);
}
}
public static boolean doesMatch(String pattern, String stringToSearch){
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(stringToSearch);
return m.find();
}
In my Application.properties file I am using a key and value like that
report.custom.templates.path=${CATALINA_HOME}\\\\Medic\\\\src\\\\main\\\\reports\\\\AllReports\\\\
I need to replace the ${CATALINA_HOME} with its actual path:
{CATALINA_HOME} = C:\Users\s57893\softwares\apache-tomcat-7.0.27
Here is my code:
public class ReadEnvironmentVar {
public static void main(String args[]) {
String path = getConfigBundle().getString("report.custom.templates.path");
System.out.println("Application Resources : " + path);
String actualPath = resolveEnvVars(path);
System.out.println("Actual Path : " + actualPath);
}
private static ResourceBundle getConfigBundle() {
return ResourceBundle.getBundle("medicweb");
}
private static String resolveEnvVars(String input) {
if (null == input) {
return null;
}
Pattern p = Pattern.compile("\\$\\{(\\w+)\\}|\\$(\\w+)");
Matcher m = p.matcher(input);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String envVarName = null == m.group(1) ? m.group(2) : m.group(1);
String envVarValue = System.getenv(envVarName);
m.appendReplacement(sb, null == envVarValue ? "" : envVarValue);
}
m.appendTail(sb);
return sb.toString();
}
}
from my code I am getting the result as -
Actual Path :
C:Userss57893softwaresapache-tomcat-7.0.27\Medic\src\main\reports\AllReports\
but I need the result as -
Actual Path :
C:\Users\s57893\softwares\apache-tomcat-7.0.27\Medic\src\main\reports\AllReports\
Please send me one example?
Because of the way appendReplacement() works, you'll need to escape backslashes that you find in the environment variable. From the Javadocs:
Note that backslashes (\) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string. Dollar signs may be treated as references to captured subsequences as described above, and backslashes are used to escape literal characters in the replacement string.
I would use:
m.appendReplacement(sb,
null == envVarValue ? "" : Matcher.quoteReplacement(envVarValue));
I like to write a java utility method that returns paramValue for paramName in specified query string
Pattern p = Pattern.compile("\\&?(\\w+)\\= (I don't know what to put here) ");
public String getParamValue(String entireQueryString, String paramName)
{
Matcher m = p.matcher(entireQueryString);
while(m.find()) {
if(m.group(1).equals(paramName)) {
return m.group(2);
}
}
return null;
}
I will be invoking this method from my servlet,
String qs = request.getQueryString(); //action=initASDF&requestId=9078-32&redirect=http://www.mydomain.com?actionId=4343
System.out.println(getParamValue(qs, "requestId"));
The output should be, 9078-32
you can use a regex negated group. See this other SO question: Regular Expressions and negating a whole character group
You'll need to get everything except a &.
Use the proper API to do it: request.getParameter("requestId")
Could you split the string based on ampersands (&) and then search the resulting array for the key (look upto the equals sign).
Here's a link to String.split(): http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split%28java.lang.String%29
Here's the type of thing I'm talking about:
private static final String KEY_VALUE_SEPARATOR = "=";
private static final String QUERY_STRING_SEPARATOR = "&";
public String getParamValue(String entireQueryString, String paramName) {
String[] fragments = entireQueryString.split(QUERY_STRING_SEPARATOR);
for (String fragment : fragments){
if (fragment.substring(0, fragment.indexOf(KEY_VALUE_SEPARATOR)).equalsIgnoreCase(paramName)){
return fragment.substring(fragment.indexOf(KEY_VALUE_SEPARATOR)+1);
}
}
throw new RuntimeException("can't find value");
}
The Exception at the end is a pretty rubbish idea but that's not really the important part of this.