Java special characters RegEx - java

I want to achieve following using Regular expression in Java
String[] paramsToReplace = {"email", "address", "phone"};
//input URL string
String ip = "http://www.google.com?name=bob&email=okATtk.com&address=NYC&phone=007";
//output URL string
String op = "http://www.google.com?name=bob&email=&address=&phone=";
The URL can contain special characters like %

Try this expression: (email=)[^&]+ (replace email with your array elements) and replace with the group: input.replaceAll("("+ paramsToReplace[i] + "=)[^&]+", "$1");
String input = "http://www.google.com?name=bob&email=okATtk.com&address=NYC&phone=007";
String output = input;
for( String param : paramsToReplace ) {
output = output.replaceAll("("+ param + "=)[^&]+", "$1");
}

For the example above. you can use split
String[] temp = ip.split("?name=")[1].split("&")[0];
op = temp[0] + "?name=" + temp[1].split("&")[0] +"&email=&address=&phone=";

Something like this?
private final static String REPLACE_REGEX = "=.+\\&";
ip=ip+"&";
for(String param : paramsToReplace) {
ip = ip.replaceAll(param+REPLACE_REGEX, Matcher.quoteReplacement(param+"=&"));
}
P.S. This is only a concept, i didn't compile this code.

You don't need regular expressions to achieve that:
String op = ip;
for (String param : paramsToReplace) {
int start = op.indexOf("?" + param);
if (start < 0)
start = op.indexOf("&" + param);
if (start < 0)
continue;
int end = op.indexOf("&", start + 1);
if (end < 0)
end = op.length();
op = op.substring(0, start + param.length() + 2) + op.substring(end);
}

Related

Masking - Address with Stars (asteriks) - If length of Array is 1?

I have an array out of bounds for this case.
If I do:
String address = "100 Point St Apt B"
It should be masked too: 100 Po*** St Apt *
If I do:
String address = "100 Point St Apt 132"
It is masked too: 100 Po*** St Apt ***
Can somebody tell me what I am doing wrong here? Thank you!!
public String mask(String address) {
String[] splitAddress = address.split(" ");
StringBuilder stringBuilder = new StringBuilder();
String maskedAddress = "";
String streetNum = splitAddress[0];
stringBuilder.append(streetNum + " ");
for (int i = 1; i < splitAddress.length; i++) {
String splitFirstTwoCharacters = splitAddress[i].substring(0, 2);
String remainingCharactersOfAddress = splitAddress[i].substring(2);
String maskAddress = remainingCharactersOfAddress.replaceAll(".", "*");
maskedAddress = stringBuilder.append(splitFirstTwoCharacters).append(maskAddress + " ").toString().trim();
}
return maskedAddress;
}
When you do splitAddress[i].substring(0, 2) one of the splitAddress parts is B which does not have an endIndex of 2. Therefore it is out of bounds.
Issue is you are running substring without checking the length of the string.
Here is the fix without too many changes to your existing code:
for (int i = 1; i < splitAddress.length; i++) {
if (splitAddress[i].length() <= 2) {
stringBuilder.append(splitAddress[i] + " ");
continue;
}
String splitFirstTwoCharacters = splitAddress[i].substring(0, 2);
String remainingCharactersOfAddress = splitAddress[i].substring(2);
String maskAddress = remainingCharactersOfAddress.replaceAll(".", "*");
maskedAddress = stringBuilder.append(splitFirstTwoCharacters).append(maskAddress + " ").toString().trim();
}
return stringBuilder.toString().trim();

Java - renaming output file if name already exists with an increment, taking into account existing increments

building an Android app i came across the need to do some file copying. I would like a way to get new filenames in the event of a filename allready being used by adding a "(increment)" string in the filename. for example
text.txt ---> text(1).txt
The algorith should account for the following
1) if text.txt exists the new file name should NEVER be text.txt(1)
2) if text(1).txt exists then new filename should be text(2).txt not text(1)(1).txt
3) if text(1)foo.txt exists the new filename should be text(1)foo(1).txt
I've allready done the first but I'm having difficulties with the second. Regular expressions is not my strong suit!(It's not mandatory to use Regex. every approach is welcome) Some help ?
ANSWER:
combining my original code and one of the answers here I ended up with this which works very well for me in all cases regardless of file having an extension or not:
public static File getFinalNewDestinationFile(File destinationFolder, File fileToCopy){
String destFolderPath = destinationFolder.getAbsolutePath()+File.separator;
File newFile = new File(destFolderPath + fileToCopy.getName());
String filename=fileToCopy.getName();
String nameWithoutExtentionOrIncrement;
String extension = getFileExtension(filename);
if(extension!=null){
extension="."+extension;
int extInd = filename.lastIndexOf(extension);
nameWithoutExtentionOrIncrement = new StringBuilder(filename).replace(extInd, extInd+extension.length(),"").toString();
}
else{
extension="";
nameWithoutExtentionOrIncrement = filename;
}
int c=0;
int indexOfClose = nameWithoutExtentionOrIncrement.lastIndexOf(")");
int indexOfOpen = nameWithoutExtentionOrIncrement.lastIndexOf("(");
if(indexOfClose!=-1 && indexOfClose!=-1 && indexOfClose==nameWithoutExtentionOrIncrement.length()-1 && indexOfClose > indexOfOpen && indexOfOpen!=0){
String possibleNumber = nameWithoutExtentionOrIncrement.substring(indexOfOpen+1, indexOfClose);
try{
c = Integer.parseInt(possibleNumber);
nameWithoutExtentionOrIncrement=nameWithoutExtentionOrIncrement.substring(0, indexOfOpen);
}catch(Exception e){c=0;}
}
while(newFile.exists()){
c++;
String path = destFolderPath + nameWithoutExtentionOrIncrement +"(" + Integer.toString(c) + ")" + extension;
newFile = new File(path);
}
return newFile;
}
public static String getFileExtension(String filename) {
if (filename == null) { return null; }
int lastUnixPos = filename.lastIndexOf('/');
int lastWindowsPos = filename.lastIndexOf('\\');
int indexOfLastSeparator = Math.max(lastUnixPos, lastWindowsPos);
int extensionPos = filename.lastIndexOf('.');
int lastSeparator = indexOfLastSeparator;
int indexOfExtension = lastSeparator > extensionPos ? -1 : extensionPos;
int index = indexOfExtension;
if (index == -1) {
return null;
} else {
return filename.substring(index + 1).toLowerCase();
}
}
Using one regex pattern:
final static Pattern PATTERN = Pattern.compile("(.*?)(?:\\((\\d+)\\))?(\\.[^.]*)?");
String getNewName(String filename) {
if (fileExists(filename)) {
Matcher m = PATTERN.matcher(filename);
if (m.matches()) {
String prefix = m.group(1);
String last = m.group(2);
String suffix = m.group(3);
if (suffix == null) suffix = "";
int count = last != null ? Integer.parseInt(last) : 0;
do {
count++;
filename = prefix + "(" + count + ")" + suffix;
} while (fileExists(filename));
}
}
return filename;
}
The regex pattern explanation:
(.*?) a non greedy "match everything" starting at the beginning
(?:\\((\\d+)\\))? a number in parenthesis (optional)
(?:____________) - is a non capturing group
___\\(______\\)_ - matches ( and )
______(\\d+)____ - matches and captures the one or more digits
(\\.[^.]+)? a dot followed by anything but a dot (optional)
Here's one way of doing it:
String fileName;
File file = new File(fileName);
if(file.exists()) {
int dot = fileName.lastIndexOf('.'), open = fileName.lastIndexOf('('), incr;
boolean validNum = false;
if(fileName.charAt(dot-1) == ')' && open != -1){
String n = fileName.substring(open+1, dot-1);
try {
incr = Integer.parseInt(n);
validNum = true;
} catch(NumberFormatException e) {
validNum = false;
}
}
if(validNum) {
String pre = fileName.substring(0, open+1), post = fileName.substring(0, dot-1);
while(new File(pre + ++incr + post).exists());
fileName = pre + incr + post;
} else {
fileName = fileName.substring(0, dot) + "(1)" + fileName.substring(dot);
}
}
I assume a couple of things:
1) A method called fileExists(String fileName) is available. It returns true if a file with the specified name is already present in the file system.
2) There is a constant called FILE_NAME which in your example case is equal to "text".
if (!fileExists(FILE_NAME)) {
//create file with FILE_NAME.txt as name
}
int availableIndex = 1;
while (true) {
if (!fileExists(currentName)) {
//create file with FILE_NAME(availableIndex).txt
break;
}
availableIndex++;
}
I am not very sure about Android but since its a Java program, you may be able to create File object of the directory in which you want to write.
Once you have this you can see the list of file names already present inside it and other related information. Then you can decide the file name as per your above logic.
File dir = new File("<dir-path>");
if(dir.isDirectory()){
String[] files = dir.list();
for(String fileName : files){
<logic for finding filename>
}
}
If all filenames have an extenstion you could do something like this (just an example you will have to change it to work in your case):
public static void main(String[] args)
{
String test = "test(1)foo.txt";
String test1 = "test(1)foo(1).txt";
Pattern pattern = Pattern.compile("((?<=\\()\\d+(?=\\)\\.))");
Matcher matcher = pattern.matcher(test);
String fileOutput = "";
String temp = null;
int newInt = -1;
while(matcher.find())
{
temp = matcher.group(0);
}
if(temp != null)
{
newInt = Integer.parseInt(temp);
newInt++;
fileOutput = test.replaceAll("\\(\\d+\\)(?=\\.(?!.*\\.))", "(" + newInt + ")");
}
else
{
fileOutput = test;
}
System.out.println(fileOutput);
matcher = pattern.matcher(test1);
fileOutput = "";
temp = null;
while(matcher.find())
{
temp = matcher.group(0);
}
if(temp != null)
{
newInt = Integer.parseInt(temp);
newInt++;
fileOutput = test1.replaceAll("\\(\\d+\\)(?=\\.(?!.*\\.))", "(" + newInt + ")");
}
else
{
fileOutput = test1;
}
System.out.println(fileOutput);
}
Output:
test(1)foo.txt
test(1)foo(2).txt
This uses regex to look for a number in the () right before the last ..
Update
replaceAll() changed to handle case where there is a . after the first (1) in test(1).foo(1).txt.

Need help in creating a regular expression in Java

I am trying to apply regex on a string to obtain the output in the below format.
Input string:
params=Param1{index}~[Value1|Value2|....]^Param2~[Value1|Value2|....]
Output should be in the form of Map<String,List<String>>
Eg.
Key1: Param1
Value : Value1,Value2 upto ValueN
Key2 :Param2
Value: Value1,Value2 uptoValueN
Code:
Her is the code that I am trying to do.
String textPatt = "params";
String key = textPatt.replace("/[\\[]/", "\\[").replace("/[\\]]/", "\\]");
String pattern = new String("[\\?&]" + key + "=([^&#]*)");
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(masterUrl);
List<String> paramList = new ArrayList<String>();
if (m.find()) {
String param = m.group();
if(param != null){
String[] multiParamArr = null;
if(param.indexOf("^") != -1){
multiParamArr = param.split("\\^");
}else{
multiParamArr = new String[1];
multiParamArr[0] = param;
}
if(multiParamArr != null && multiParamArr .length > 0){
Pattern refinePattern = null;
Matcher refineMatcher = null;
String paramKeyy = null;
String paramVal = null;
HashMap<String,List<String>> ParamMap = new HashMap<String,List<String>>();
List<String list = new ArrayList<String>();
for(int i=0;i<multiParamArr.length;i++){
String[] multiParam = null;
String patternKey = "^[^\\~]*";
refinePattern = Pattern.compile(patternKey);
refineMatcher = refinePattern.matcher(multiRefineArr[i]);
if(refineMatcher.find()){
paramKey = refineMatcher.group();
if(paramKey.indexOf("=") !=-1){
patternKey = patternKey.substring(patternKey.indexOf("=")+1);
}
if(paramKey.indexOf("{") !=-1){
patternKey = patternKey.substring(patternKey.indexOf("=")+1,patternKey.indexOf("{"));
}
}
if(multiParamArr[i].indexOf("|") != -1){
multiParam = multiParamArr[i].split("\\|");
int startIndex;
int endIndex;
for(int j=0;j<multiParam.length;j++){
startIndex = 0;
endIndex = 0;
ifmultiParamArr[j].indexOf("[") > -1){
startIndex = multiParamArr[j].indexOf("[")+1;
}
ifmultiParamArr[j].indexOf("]") > -1){
endIndex = multiParamArr[j].indexOf("]");
}else{
endIndex = multiParamArr[j].length();
}
paramVal = multiParamArr[j].substring(startIndex,endIndex);
}
}else{
paramVal = multiParamArr[i].substring(multiParamArr[i].indexOfmultiParamArr[i].indexOf("]"));
}
list.add(paramVal);
}
paramMap.put((paramKey,list);
}
}
}
how to apply a single regex and achieve the output
Instead of trying to create a complex regex and maintain it, you can do it simpler and in a more readable way, in a few steps:
Split on ^
Now you have an array of Strings, each of which contains one of the parameters with its values
Split each string on ~ - you'll get an array of two strings, extract from the first the Param1 (Param2 etc)
From the second you can extract the list of values by splitting on
| (pipe).

String representation of List<String> list

I hava a List<String> that I need to serialize or make a String representation.
For example I have:
myList.add("Bob");
myList.add("account");
myList.add("userId");
The list can contain variable number of items and I need it to be serialized in this form:
\Bob\-\account\-\userId\
I can do a for loop like:
String ss;
for (String s: myList) {
s = "\\" + s + "\\";
ss = s + "-";
}
However there will be a "-" in the tail of the resulting String ss
Or is there a Google Guava function to do this already?
Using Guava:
String s = Joiner.on('-').join(Iterables.transform(list, new Function<String, String>() {
#Override
public String apply(String input) {
return "\\" + input + "\\";
}
});
The straight-forward way to solve this using Guava is the Joiner:
System.out.println("\\" + Joiner.on("\\-\\").join(myList) + "\\");
You can easily use Apaches Commons StringUtils:
String ss = "\\" + StringUtils.join(myList.iterator(), "\\-\\") + "\\";
Firstly, it is recommended to use StringBuilder during such concatenations.
Secondly, you can use Apache Common Lang's StringUtils.join()` method as follows to achieve the same:
ss = "\\" + StringUtils.join(myList.iterator(), "\\-\\") + "\\";
You can fix it by changing your loop like:
String ss = "";
for (String s: myList) {
s = "\\" + s + "\\";
if(ss.equals("")) {
ss = s;
}
else {
ss += " - " + s;
}
}
Perhaps the other solutions is an old fashioned for loop which is based on the List size().
The other thing I would do is use a StringBuffer as it is more efficient than concatenating Strings. Internally when you concatenate a String, the object is destroyed and recreated.
int myListSize = myList.size();
StringBuffer ss = new StringBuffer(4);
for (int i=0; i < myListSize; i++) {
ss.append("\\").append(myList.get(i)).append("\\");
if (i < myListSize - 1) {
ss.append("-");
}
}
Then to output from a StringBuffer:
ss.toString();
Personally I think these for loops (as above) end up being easier to read.
The simplest code for string joining that I know goes like this:
String sep = "", out = "";
for (String s : myList) {
out += sep + '\\' + s + '\\';
sep = "-";
}

Words inside square brackes - RegExp

String linkPattern = "\\[[A-Za-z_0-9]+\\]";
String text = "[build]/directory/[something]/[build]/";
RegExp reg = RegExp.compile(linkPattern,"g");
MatchResult matchResult = reg.exec(text);
for (int i = 0; i < matchResult.getGroupCount(); i++) {
System.out.println("group" + i + "=" + matchResult.getGroup(i));
}
I am trying to get all blocks which are encapsulated by squared bracets form a path string:
and I only get group0="[build]" what i want is:
1:"[build]" 2:"[something]" 3:"[build]"
EDIT:
just to be clear words inside the brackets are generated with random text
public static String genText()
{
final int LENGTH = (int)(Math.random()*12)+4;
StringBuffer sb = new StringBuffer();
for (int x = 0; x < LENGTH; x++)
{
sb.append((char)((int)(Math.random() * 26) + 97));
}
String str = sb.toString();
str = str.substring(0,1).toUpperCase() + str.substring(1);
return str;
}
EDIT 2:
JDK works fine, GWT RegExp gives this problem
SOLVED:
Answer from Didier L
String linkPattern = "\\[[A-Za-z_0-9]+\\]";
String result = "";
String text = "[build]/directory/[something]/[build]/";
RegExp reg = RegExp.compile(linkPattern,"g");
MatchResult matchResult = null;
while((matchResult=reg.exec(text)) != null){
if(matchResult.getGroupCount()==1)
System.out.println( matchResult.getGroup(0));
}
I don't know which regex library you are using but using the one from the JDK it would go along the lines of
String linkPattern = "\\[[A-Za-z_0-9]+\\]";
String text = "[build]/directory/[something]/[build]/";
Pattern pat = Pattern.compile(linkPattern);
Matcher mat = pat.matcher(text);
while (mat.find()) {
System.out.println(mat.group());
}
Output:
[build]
[something]
[build]
Try:
String linkPattern = "(\\[[A-Za-z_0-9]+\\])*";
EDIT:
Second try:
String linkPattern = "\\[(\\w+)\\]+"
Third try, see http://rubular.com/r/eyAQ3Vg68N

Categories

Resources