Java Regex - Changing path with an alias - java

I have a path called $SERVER/public_html/ab1/ab2/.
I want to change it so that instead of $SERVER it just replaces it with my user directory. So I do
path = path.replaceFirst("\\$SERVER", System.getProperty("user.dir"));
but when I run it, it removes my \ in the new string.
F:Programming ProjectsJava Project/public_html/ab1/ab2/

Pattern has a String quote(String) function that will help you for the first string and Matcher has String quoteReplacement(String) for the second:
path = path.replaceFirst(java.util.regex.Pattern.quote("$SERVER"), java.util.regex.Matcher.quoteReplacement(System.getProperty("user.dir")));
edit: the reason you have to escape anything is because the second string has the semantics of Matcher.appendReplacement which treats backslashes and dollars as escape next char and insert captured group resp.
from the doc:
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.
a more obvious solution is (be careful of the needed escaped with that backslash)
path = path.replaceFirst("\\$SERVER", System.getProperty("user.dir").replaceAll("\\\\","\\\\\\\\"));

Yea you are completly right. I am trying to figure out why it is happening so.
But at the moment the only think I can suggest is to go with such a solution.
public class RegExTest
{
public static void main(String[] args)
{
String path = "$SERVER/public_html/ab1/ab2";
System.out.println("path before="+path);
String user = System.getProperty("user.dir");
System.out.println("user="+user);
System.out.println("replaceFirst using user="+path.replaceFirst("\\$SERVER", user));
path = path.replaceFirst("\\$SERVER", "");
path = user +path;
System.out.println("path after="+path);
}
}
EDIT: ..Why it does that?
From what I see in the code of the method line 701 to 708 they must do it. They just skip them. As to the reason why they do it, I still am not sure.
EDIT2:
OK reading the doc for the method answers it all. They do it so they can interpret accordingly special characters. Thus when reading the replacement they spot a slash the algorithm assumes it can be a part of special character and in result skips it.
if (nextChar == '\\') {
cursor++;
nextChar = replacement.charAt(cursor);
result.append(nextChar);
cursor++;
} else if (nextChar == '$') {
// Skip past $
cursor++;

Ok so in Windows the default slashes look like so '\' whereas on *nix the slashes look like so '/' . The simplest way to get through this problem is to invoke the replace function with the following parameters '\\' and '/' . That way you path will have its slashes all facing the same way.

Related

Regex pattern to validate Linux folder path

Using JAVA.
I am trying to find a more elegant way for validating a Linux folder path (not including the file name).
What I have so far is this: "^\\/$|^((\\/([a-zA-Z0-9_-]+))+)$"
Folder paths should include only following characters: letters, numbers, dashes or underscore.
Test cases
Valid/ matches:
/
/abc
/abc/abc/abc/abc
Invalid / not-matches:
null or empty string
/abc/
/abc/abc/abc/abc/
Issue with your RegEx
Your supplied RegEx is working on the test-cases.
You could even reduce it by removing backslashes \\ and outer pair of parentheses. Begin ^ and end $ are only needed once (around the two alternatives).
Possible Solution using Regular Expression
You can test the RegEx on RegexPlanet.com (click on Java-Button for tests)
^/|(/[a-zA-Z0-9_-]+)+$
or equivalent (see demo on RegexPlanet)
^/|(/[\w-]+)+$
Explained:
\w matches a word-character (same as [a-zA-Z0-9_], not matching the dash).
Implementation in Java code:
public boolean isValidLinuxDirectory(String path) {
Pattern linuxDirectoryPattern = Pattern.compile("^/|(/[a-zA-Z0-9_-]+)+$");
return path != null && !path.trim().isEmpty() && linuxDirectoryPattern.matcher( path ).matches();
}
Alternative Solution using File
Note the docs on isDirectory():
Returns:
true if and only if the file denoted by this abstract pathname exists and is a directory; false otherwise
So it may only validate your requirements (valid Linux folder) if run on a Linux machine and if the folder/directory exists.
public boolean isValidExistingDirectory(String path) {
if (path == null || path.trim().isEmpty()) return false;
File file = new File( path );
return file.isDirectory();
}
Extended Solution
As stated in comment the special form of root // should also be valid. Then use this RegEx:
^/|//|(/[\w-]+)+$
It supports:
root-directory /
special form of root-directory //
any non-root directory, which name is composed out of alphas, numbers, dash or underscore (e.g. /abc/123/_abc-123)
See also
What is the most correct regular expression for a UNIX file path?
Regular expression to validate windows and linux path with extension
what is path //, how is it different from /
Here ya go:
\/[a-zA-Z0-9_\/-]*[^\/]$
EDIT
First character matches a forward slash /. The following character group matches a-z, A-Z, 0-9, underscores, forward slashes, and dashes (all accepted directory and filename characters). The following asterisk makes the pattern match that character group 0 or more times (so any combo of those characters). The last character group has a negation ^ meaning it matches anything EXCEPT what's in the character group, being the final forward slash that we don't want to match. Finally the $ to end the string.
To cover all cases including the root directory, you will need the following:
^\/$|(\/[a-zA-Z_0-9-]+)+$
See Regex Demo using global and multiline modifiers.

How to get File Path with double-backslashes in Java

I have a program where I save school grades in a .txt File.
I want to let the user choose where this File should be saved.
It works with the JFileChooser find but Java have a problem with the
FilePath.
The filepath from the JFileChooser looks like this:
C:\Users...\Documents\n.txt
But if I want to read the TextFile in the Program Java says that
it couldn't find the Filepath.
It should look like this:
C:\Users\...\Documents\n.txt
How can I get the Path with double-backslashes?
public void actionPerformed(ActionEvent e) {
JFileChooser jf = new JFileChooser();
jf.showSaveDialog(null);
String fPath = jf.getSelectedFile().getPath();
fPath.replaceAll('\', '\\');
System.out.println(p);
}
that does not work it says invalid character constant
There are some places where the backslash serves as escape character, and must be escaped, to be simply the backslash of a Windows path separator.
These places are inside .properties files, java String literals and some more.
You could for Windows paths alternatively use a slash (POSIX compliance of Windows).
fPath = fPath.replace('\\', '/');
Backslash:
fPath = fPath.replace("\\", "\\\\");
The explanation is that a single backslash inside char and string literals must be escaped: two backslashes represent a single backslash.
With regular expressions (replaceAll) a backlash is used as command: a digit is expressed as \d and as java String: "\\d". Hence the backslash itself becomes (behold):
fPath = fPath.replaceAll("\\\\", "\\\\\\\\"); // PLEASE NOT
I almost did not see it, but methods on String do not alter it, but return a new value, so one needs to assign the result.
When using hard coded file names in Java you should always use forward slashes / as file separators. Java knows how to handle them on Windows.
Also you should not use absolute paths. You don't know if that paths will exist at the target system. You should use either relative paths starting with your classpath as root "/..." or get some system dependen places from System.getProperty() https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getProperties--
Multiple issues in your code:
public void actionPerformed(ActionEvent e) {
JFileChooser jf = new JFileChooser();
jf.showSaveDialog(null);
String fPath = jf.getSelectedFile().getPath();
// fPath is a proper file path. This can be used directly with
// new File(fPath). The contents will contain single \ character
// as Path separator
fPath.replaceAll('\', '\\');
// I guess you are trying to replace a single \ character with \\
// character. You need to escape the \ character. You need to
// consider that both parameters are regexes.
// doing it is:
// fPath.replaceAll("\\\\", "\\\\\\\\");
// And then you need to capture the return value. Strings are
// immutable in java. So it is:
// fPath = fPath.replaceAll("\\\\", "\\\\\\\\");
System.out.println(p);
// I don't know what p is. I guess you want to use fPath
}
That said, I do not understand why you want to convert the path returned by JFileChooser.
You don't need the file path with double backslashes in Java. Double backslashes are for:
The Java compiler, inside string literals.
The Java regex compiler.
Everywhere else you can obtain backslashes, or use forward slashes.
Possibly you are looking for java.util.Properties?

Java regex for Windows file path

I'm trying to build a Java regex to search a .txt file for a Windows formatted file path, however, due to the file path containing literal backslashes, my regex is failing.
The .txt file contains the line:
C\Windows\SysWOW64\ntdll.dll
However, some of the filenames in the text file are formatted like this:
C\Windows\SysWOW64\ntdll.dll (some developer stuff here...)
So I'm unable to use String.equals
To match this line, I'm using the regex:
filename = "C\\Windows\\SysWOW64\\ntdll.dll"
read = BufferedReader.readLine();
if (Pattern.compile(Pattern.quote(filename), Pattern.CASE_INSENSITIVE).matcher(read).find()) {
I've tried escaping the literal backslashes, using the replace method, i.e:
filename.replace("\\", "\\\\");
However, this is failing to find, I'm guessing this is because I need to further escape the backslashes after the Pattern has been built, I'm thinking I might need to escape upto an additional four backslashes, i.e:
Pattern.replaceAll("\\\\", "\\\\\\\\");
However, each time I try, the pattern doesn't get matched. I'm certain it's a problem with the backslashes, but I'm not sure where to do the replacement, or if there's a better way of building the pattern.
I think the problem is further being compounded as the replaceAll method also uses a regex, with means the pattern will have it's own backslashes in there, to deal with the case insensitivity.
Any input or advice would be appreciated.
Thanks
Seems like you're attempting to to a direct comparison of String against another. For exact matches, you could do (
if (read.equalsIgnoreCase(filename)) {
of simply
if (read.startsWith(filename)) {
Try this :
While reading each line from the file, replace '\' by '\\'.
Then :
String lLine = "C\\Windows\\SysWOW64\\ntdll.dll";
Pattern lPattern = Pattern.compile("C\\\\Windows\\\\SysWOW64\\\\ntdll\\.dll");
Matcher lMatcher = lPattern.matcher(lLine);
if(lMatcher.find()) {
System.out.println(lMatcher.group());
}
lLine = "C\\Windows\\SysWOW64\\ntdll.dll (some developer stuff here...)";
lMatcher = lPattern.matcher(lLine);
if(lMatcher.find()) {
System.out.println(lMatcher.group());
}
The correct usage will be:
String filename = "C\\Windows\\SysWOW64\\ntdll.dll";
String file = filename.replace('\\', ' ');

Replace "\\" with "/" in Java

I am trying to replace '\\'with '/' in java(Android) and this does not seem to work!
String rawPath = filePath.replace("\\\\", "/");
What is wrong with this ? I have escaped "\" and tried escaping '/' but to no use. Nothing happens to the original string.
filePath = abc\\xyz(not after escaping two \\, the original string is with two \\)
rawPath = abc \ xyz
expected = abc/xyz
Whats the correct way of doing this? (Another Windows file to Android path conversion prob)
When using String.replace(String, String) the backslash doesn't need to be escaped twice (thats when using replaceAll - it deals with regex). So:
String rawPath = filePath.replace("\\", "/");
Or using char version:
String rawPath = filePath.replace('\\', '/');
You do not need the quad-druple escape,
\\\\
, just simply
\\
.
escape with single slash should be enough. Following is working fine for me.
String rawPath = filePath.replace("\\", "/");
public static void main(String[] args) {
String s = "foo\\\\bar";
System.out.println(s);
System.out.println(s.replace("\\\\", "/"));
}
will print
foo\\bar
foo/bar
If you want to replace a sequence of 2 backslashes in your original string with a single forward slash, this should work:
String filePath = "abc\\\\xyz";
String rawPath = filePath.replace("\\\\", "/");
System.out.println(filePath);
System.out.println(rawPath);
outputs:
abc\\xyz
abc/xyz
Do you really have two backslashes in the String in the first place? That only appears in Java source code. At runtime there will only be one backslash. So the task reduces to changing backslashes to forward slashes (why?). For which you need a regex if you are using replaceAll(), which would require four of them: two for the compiler, and two for the regex, but you aren't using that, you are using replace(), which isn't a regex, so you only need two, one for the compiler and one for itself.
Why are you doing this? It is never necessary to use a backslash in a File path in Java at all, and it is also never necessary to translate them to / unless you are doing URL-like things with them, in which case there are File.toURI() methods and URI and URL classes for that.
Here is a very small method to get the desktop path and show you how to replace them in the return statement.
public static String getDesktopPath() {
String desktopPath = System.getProperty("user.home") + "/Desktop";
return desktopPath.replace("\\", "/");
}

Replace backslashes in a string using Java/Groovy

Trying to get a simple string replace to work using a Groovy script. Tried various things, including escaping strings in various ways, but can't figure it out.
String file ="C:\\Test\\Test1\\Test2\\Test3\\"
String afile = file.toString() println
"original string: " + afile
afile.replace("\\\\", "/")
afile.replaceAll("\\\\", "/") println
"replaced string: " + afile
This code results in:
original string: C:\Test\Test1\Test2\Test3\
replaced string: C:\Test\Test1\Test2\Test3\
----------------------------
The answer, as inspired by Sorrow, looks like this:
// first, replace backslashes
String afile = file.toString().replaceAll("\\\\", "/")
// then, convert backslash to forward slash
String fixed = afile.replaceAll("//", "/")
replace returns a different string. In Java Strings cannot be modified, so you need to assign the result of replacing to something, and print that out.
String other = afile.replaceAll("\\\\", "/")
println "replaced string: " + other
Edited: as Neftas pointed in the comment, \ is a special character in regex and thus have to be escaped twice.
In Groovy you can't even write \\ - it is "an unsupported escape sequence". So, all answers I see here are incorrect.
If you mean one backslash, you should write \\\\. So, changing backslashes to normal slashes will look as:
scriptPath = scriptPath.replaceAll("\\\\", "/")
If you want to replace pair backslashes, you should double the effort:
scriptPath = scriptPath.replaceAll("\\\\\\\\", "/")
Those lines are successfully used in the Gradle/Groovy script I have intentionally launched just now once more - just to be sure.
What is even more funny, to show these necessary eight backslashes "\\\\\\\\" in the normal text here on StackOverflow, I have to use sixteen of them! Sorry, I won't show you these sixteen, for I would need 32! And it will never end...
If you're working with paths, you're better off using the java.io.File object. It will automatically convert the given path to the correct operating-system dependant path.
For example, (on Windows):
String path = "C:\\Test\\Test1\\Test2\\Test3\\";
// Prints C:\Test\Test1\Test2\Test3
System.out.println(new File(path).getAbsolutePath());
path = "/Test/Test1/Test2/Test3/";
// Prints C:\Test\Test1\Test2\Test3
System.out.println(new File(path).getAbsolutePath());
1) afile.replace(...) doesn't modify the string you're calling it on, it just returns a new string.
2) The input strings (String file ="C:\\Test\\Test1\\Test2\Test3\\";), from Java's perspective, only contain single backslashes. The first backslash is the escape character, then the second backslash tells it that you actually want a backslash.
so
afile.replace("\\\\", "/");
afile.replaceAll("\\\\", "/");
should be...
afile = afile.replace("\\", "/");
afile = afile.replaceAll("\\", "/");
In Groovy you can use regex in this way as well:
afile = afile.replaceAll(/(\\)/, "/")
println("replaced string: "+ afile)
Note that (as Sorrow said) replaceAll returns the result, doesn't modify the string. So you need to assign to a var before printing.
String Object is immutable so if you call a method on string object that modifies it. It will always return a new string object(modified). So you need to store the result return by replaceAll() method into a String object.
As found here, the best candidate might be the static Matcher method:
Matcher.quoteReplacement( ... )
According to my experiments this doubles single backslashes. Despite the method name... and despite the slightly cryptic Javadoc: "Slashes ('\') and dollar signs ('$') will be given no special meaning"

Categories

Resources