Using regex on XML, avoid greedy match - java

It looks simple problem , but I'll apprisiate any help here :
I need to swap password value (can be any value) to "****"
The origunal sting is string resived from xml
The problem is that I getting as output only line:
<parameter><value>*****</value></parameter>
But I need the whole string as output only with password value replaced
Thank you in advance
String originalString = "<parameter>" +
"<name>password</name>"+
"<value>my123pass</value>"+
"</parameter>"+
"<parameter>"+
"<name>LoginAttempt</name>"+
"<value>1</value>"+
"</parameter>";
System.out.println("originalString: "+originalString);
Pattern pat = Pattern.compile("<name>password</name><value>.*</value>");
Matcher mat = pat.matcher(originalString);
System.out.println("NewString: ");
System.out.print(mat.replaceFirst("<value>***</value>"));
mat.reset();

If I'm not mistaken, you want to change the password in the string with *'s. You can do it by using String methods directly. Just get the last index of the starting value tag and iterate until you reach a "<", replacing the value between those two with *'s. Something like this:
int from = originalString.lastIndexOf("<name>password</name><value>");
bool endIteration = false;
for(i = from + 1 ; i < originalString.length() && !endIteration ; i ++) {
if(originalString.toCharArray()[i] == '<')
endIteration = true;
else {
originalString.toCharArray()[i] = '*';
}
}
EDIT: There is another way making a proper use of all the String class goodies:
int from = originalString.lastIndexOf("<name>password</name><value>");
int to = originalString.indexOf("</value>", from);
Arrays.fill(originalString.toCharArray(), from, to, '*');

Related

Remove characters from string builder

I'm trying to run a loop to remove some characters from a string. but when I'm running the following code I get output(I on) only from the first run. I don't get the rest of the string. Can someone please help what I need to add here ? only shows the result from the first iteration. Thanks
someStr = "I don't know this";
StringBuilder sb = new StringBuilder(someStr);
int n = 3
for (int i = n - 1; i < sb.length(); i = n + 1) {
sb = sb.deleteCharAt(i);
}
System.out.println(sb.toString());
The third part of the for statement is the instruction that should increment or decrement your index.
There, it is always 4.
To be clearer :
1st iteration : i = 2 => you remove the 'd', your string is now "I on't know this"
2nd iteration : i = 4 => you remove the ''', your string is now "I ont know this"
3rd iteration : i = 4 => you remove the 't', your string is now "I on know this"
4th iteration : i = 4 => you remove the ' ', your string is now "I onknow this"
...
If you want to remove characters from a String I recommend you to use Regex. This is an example to replace with empty strings the characters that you need to remove:
public static String cleanWhitPattern(String sample, String , String regex) {
if (sample != null && regex != null) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sample);
if (matcher.find()) {
return matcher.replaceAll("");
}
return sample;
}
return null;
}
Now, you simply call this method with your required pattern:
System.out.print(cleanWithPattern("I don't know this", "o*"));
And your output should be this:
I dn't knw this
Why not use String.replaceAll()?
someStr = "I don't know this";
System.out.print("Output :" );
System.out.println(someStr .replaceAll("t", ""));
For example, if you want to remove the char "k" from your string then you can do the following
JAVA:
String someStr = "I don't know this";
StringBuilder sb = new StringBuilder(someStr);
if(sb.toString().contains("k")){
int index = sb.indexOf("k");
sb.deleteCharAt(index);
System.out.println(sb.toString());
}else{
System.out.println("No such a char");
}
KOTLIN:
val someStr: String = "I don't know this"
val sb: StringBuilder = StringBuilder(someStr)
if(sb.toString().contains("k")){
val index: Int = sb.indexOf("k")
sb.deleteCharAt(index)
print(sb.toString())
}else{
print("No such a char")
}
Of course, you can do many combinations or many improvements depends of your desired output.

masking of email address in java

I am trying to mask email address with "*" but I am bad at regex.
input : nileshxyzae#gmail.com
output : nil********#gmail.com
My code is
String maskedEmail = email.replaceAll("(?<=.{3}).(?=[^#]*?.#)", "*");
but its giving me output nil*******e#gmail.com I am not getting whats getting wrong here. Why last character is not converted?
Also can someone explain meaning all these regex
Your look-ahead (?=[^#]*?.#) requires at least 1 character to be there in front of # (see the dot before #).
If you remove it, you will get all the expected symbols replaced:
(?<=.{3}).(?=[^#]*?#)
Here is the regex demo (replace with *).
However, the regex is not a proper regex for the task. You need a regex that will match each character after the first 3 characters up to the first #:
(^[^#]{3}|(?!^)\G)[^#]
See another regex demo, replace with $1*. Here, [^#] matches any character that is not #, so we do not match addresses like abc#example.com. Only those emails will be masked that have 4+ characters in the username part.
See IDEONE demo:
String s = "nileshkemse#gmail.com";
System.out.println(s.replaceAll("(^[^#]{3}|(?!^)\\G)[^#]", "$1*"));
If you're bad at regular expressions, don't use them :) I don't know if you've ever heard the quote:
Some people, when confronted with a problem, think
"I know, I'll use regular expressions." Now they have two problems.
(source)
You might get a working regular expression here, but will you understand it today? tomorrow? in six months' time? And will your colleagues?
An easy alternative is using a StringBuilder, and I'd argue that it's a lot more straightforward to understand what is going on here:
StringBuilder sb = new StringBuilder(email);
for (int i = 3; i < sb.length() && sb.charAt(i) != '#'; ++i) {
sb.setCharAt(i, '*');
}
email = sb.toString();
"Starting at the third character, replace the characters with a * until you reach the end of the string or #."
(You don't even need to use StringBuilder: you could simply manipulate the elements of email.toCharArray(), then construct a new string at the end).
Of course, this doesn't work correctly for email addresses where the local part is shorter than 3 characters - it would actually then mask the domain.
Your Look-ahead is kind of complicated. Try this code :
public static void main(String... args) throws Exception {
String s = "nileshkemse#gmail.com";
s= s.replaceAll("(?<=.{3}).(?=.*#)", "*");
System.out.println(s);
}
O/P :
nil********#gmail.com
I like this one because I just want to hide 4 characters, it also dynamically decrease the hidden chars to 2 if the email address is too short:
public static String maskEmailAddress(final String email) {
final String mask = "*****";
final int at = email.indexOf("#");
if (at > 2) {
final int maskLen = Math.min(Math.max(at / 2, 2), 4);
final int start = (at - maskLen) / 2;
return email.substring(0, start) + mask.substring(0, maskLen) + email.substring(start + maskLen);
}
return email;
}
Sample outputs:
my.email#gmail.com > my****il#gmail.com
info#mail.com > i**o#mail.com
//In Kotlin
val email = "nileshkemse#gmail.com"
val maskedEmail = email.replace(Regex("(?<=.{3}).(?=.*#)"), "*")
public static string GetMaskedEmail(string emailAddress)
{
string _emailToMask = emailAddress;
try
{
if (!string.IsNullOrEmpty(emailAddress))
{
var _splitEmail = emailAddress.Split(Char.Parse("#"));
var _user = _splitEmail[0];
var _domain = _splitEmail[1];
if (_user.Length > 3)
{
var _maskedUser = _user.Substring(0, 3) + new String(Char.Parse("*"), _user.Length - 3);
_emailToMask = _maskedUser + "#" + _domain;
}
else
{
_emailToMask = new String(Char.Parse("*"), _user.Length) + "#" + _domain;
}
}
}
catch (Exception) { }
return _emailToMask;
}

Inserting Newline character before every number occurring in a string?

I have String of format something like this
String VIA = "1.NEW DELHI 2. Lucknow 3. Agra";
I want to insert a newline character before every digit occurring succeeded a dot so that it final string is like this
String VIA = "1.NEW DELHI " +"\n"+"2. Lucknow " +"\n"+"3. Agra";
How can I do it. I read Stringbuilder and String spilt, but now I am confused.
Something like:
StringBuilder builder = new StringBuilder();
String[] splits = VIA.split("\d+\.+");
for(String split : splits){
builder.append(split).append("\n");
}
String output = builder.toString().trim();
The safest way here to do that would be go in a for loop and check if the char is a isDigit() and then adding a '\n' before adding it to the return String. Please note, I am not sure if you want to put a '\n' before the first digit.
String temp = "";
for(int i=0; i<VIA.length(); i++) {
if(Character.isDigit(VIA.charAt(i)))
temp += "\n" + VIA.charAt(i);
} else {
temp += VIA.charAt(i);
}
}
VIA = temp;
//just use i=1 here of you want to skip the first charachter or better do a boolean check for first digit.

Checking whether the String contains multiple words

I am getting the names as String. How can I display in the following format: If it's single word, I need to display the first character alone. If it's two words, I need to display the first two characters of the word.
John : J
Peter: P
Mathew Rails : MR
Sergy Bein : SB
I cannot use an enum as I am not sure that the list would return the same values all the time. Though they said, it's never going to change.
String name = myString.split('');
topTitle = name[0].subString(0,1);
subTitle = name[1].subString(0,1);
String finalName = topTitle + finalName;
The above code fine, but its not working. I am not getting any exception either.
There are few mistakes in your attempted code.
String#split takes a String as regex.
Return value of String#split is an array of String.
so it should be:
String[] name = myString.split(" ");
or
String[] name = myString.split("\\s+);
You also need to check for # of elements in array first like this to avoid exception:
String topTitle, subTitle;
if (name.length == 2) {
topTitle = name[0].subString(0,1);
subTitle = name[1].subString(0,1);
}
else
topTitle = name.subString(0,1);
The String.split method split a string into an array of strings, based on your regular expression.
This should work:
String[] names = myString.split("\\s+");
String topTitle = names[0].subString(0,1);
String subTitle = names[1].subString(0,1);
String finalName = topTitle + finalName;
First: "name" should be an array.
String[] names = myString.split(" ");
Second: You should use an if function and the length variable to determine the length of a variable.
String initial = "";
if(names.length > 1){
initial = names[0].subString(0,1) + names[1].subString(0,1);
}else{
initial = names[0].subString(0,1);
}
Alternatively you could use a for loop
String initial = "";
for(int i = 0; i < names.length; i++){
initial += names[i].subString(0,1);
}
You were close..
String[] name = myString.split(" ");
String finalName = name[0].charAt(0)+""+(name.length==1?"":name[1].charAt(0));
(name.length==1?"":name[1].charAt(0)) is a ternary operator which would return empty string if length of name array is 1 else it would return 1st character
This will work for you
public static void getString(String str) throws IOException {
String[] strr=str.split(" ");
StringBuilder sb=new StringBuilder();
for(int i=0;i<strr.length;i++){
sb.append(strr[i].charAt(0));
}
System.out.println(sb);
}

Java: slicing a String

I have URLs which always end on a number, for example:
String url = "localhost:8080/myproject/reader/add/1/";
String anotherurl = "localhost:8080/myproject/actor/take/154/";
I want to extract the number between the last two slashes ("/").
Does anyone know how I can do this?
You could split the string:
String[] items = url.split("/");
String number = items[items.length-1]; //last item before the last slash
With a regular expression:
final Matcher m = Pattern.compile("/([^/]+)/$").matcher(url);
if (m.find()) System.out.println(m.group(1));
Use lastIndexOf, like this:
String url = "localhost:8080/myproject/actor/take/154/";
int start = url.lastIndexOf('/', url.length()-2);
if (start != -1) {
String s = url.substring(start+1, url.length()-1);
int n = Integer.parseInt(s);
System.out.println(n);
}
That's the basic idea. You'll have to do some error checking (for example, if a number is not found at the end of the URL), but it will work fine.
For the inputs which you specified
String url = "localhost:8080/myproject/reader/add/1/";
String anotherurl = "localhost:8080/myproject/actor/take/154/";
adding a little error handling to handle missing "/" like
String url = "localhost:8080/myproject/reader/add/1";
String anotherurl = "localhost:8080/myproject/actor/take/154";
String number = "";
if(url.endsWith("/") {
String[] urlComps = url.split("/");
number = urlComps[urlComps.length-1]; //last item before the last slash
} else {
number = url.substring(url.lastIndexOf("/")+1, url.length());
}
In One Line :
String num = (num=url.substring(0, url.length() - 1)).substring(num.lastIndexOf('/')+1,num.length());

Categories

Resources