Java- Decode hex escaping characters in string [duplicate] - java

I'm looking for a very simple way of getting the equivalent of something like the following JavaScript code. That is, for each match I would like to call a certain transformation function and use the result as the replacement value.
var res = "Hello World!".replace(/\S+/, function (word) {
// Since this function represents a transformation,
// replacing literal strings (as with replaceAll) are not a viable solution.
return "" + word.length;
})
// res => "5 6"
Only .. in Java. And, preferably as a "single method" or "template" that can be reused.

Your answer is in the Matcher#appendReplacement documentation. Just put your function call in the while loop.
[The appendReplacement method] is intended to be used in a loop together with the appendTail and find methods. The following code, for example, writes one dog two dogs in the yard to the standard-output stream:
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());

Since Java 9 Matcher.replaceAll:
Pattern.compile("\\S+").matcher("Hello World!")
.replaceAll(mr -> "" + mr.group().length());
The parameter freely named mr is a MatchResult, with access methods like mr.group(1) or mr.end() - mr.start().

When allowing Java 8 you can use Lambda-Expressions, to have a JavaScript like replace:
String result = StringReplacer.replace("Hello World!", Pattern.compile("\\S+"), m -> ("" + m.group().length()));
StringReplacer.java:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringReplacer {
public static String replace(String input, Pattern regex, Function<Matcher, String> callback) {
StringBuffer resultString = new StringBuffer();
Matcher regexMatcher = regex.matcher(input);
while (regexMatcher.find()) {
regexMatcher.appendReplacement(resultString, callback.apply(regexMatcher));
}
regexMatcher.appendTail(resultString);
return resultString.toString();
}
}
Source: http://www.whitebyte.info/programming/string-replace-with-callback-in-java-like-in-javascript

Not sure what your precise requirements are but something like this could work:
String res = "";
for (String piece : "hello world".split(" "))
res += Integer.toString(piece.length()) + " ";
Of course there are other ways to write that, and tweaks that can be made depending on requirements (e.g. use a more accurate delimiter than a space).
For a precise implementation of your snippet, you could use e.g. StreamTokenizer with a StringReader and some wrappers to parse out the delimiters and insert them between the counts.

Related

Java split a string by using a regex [duplicate]

I have a string that has two single quotes in it, the ' character. In between the single quotes is the data I want.
How can I write a regex to extract "the data i want" from the following text?
mydata = "some string with 'the data i want' inside";
Assuming you want the part between single quotes, use this regular expression with a Matcher:
"'(.*?)'"
Example:
String mydata = "some string with 'the data i want' inside";
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find())
{
System.out.println(matcher.group(1));
}
Result:
the data i want
You don't need regex for this.
Add apache commons lang to your project (http://commons.apache.org/proper/commons-lang/), then use:
String dataYouWant = StringUtils.substringBetween(mydata, "'");
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
Pattern pattern = Pattern.compile(".*'([^']*)'.*");
String mydata = "some string with 'the data i want' inside";
Matcher matcher = pattern.matcher(mydata);
if(matcher.matches()) {
System.out.println(matcher.group(1));
}
}
}
There's a simple one-liner for this:
String target = myData.replaceAll("[^']*(?:'(.*?)')?.*", "$1");
By making the matching group optional, this also caters for quotes not being found by returning a blank in that case.
See live demo.
Since Java 9
As of this version, you can use a new method Matcher::results with no args that is able to comfortably return Stream<MatchResult> where MatchResult represents the result of a match operation and offers to read matched groups and more (this class is known since Java 1.5).
String string = "Some string with 'the data I want' inside and 'another data I want'.";
Pattern pattern = Pattern.compile("'(.*?)'");
pattern.matcher(string)
.results() // Stream<MatchResult>
.map(mr -> mr.group(1)) // Stream<String> - the 1st group of each result
.forEach(System.out::println); // print them out (or process in other way...)
The code snippet above results in:
the data I want
another data I want
The biggest advantage is in the ease of usage when one or more results is available compared to the procedural if (matcher.find()) and while (matcher.find()) checks and processing.
Because you also ticked Scala, a solution without regex which easily deals with multiple quoted strings:
val text = "some string with 'the data i want' inside 'and even more data'"
text.split("'").zipWithIndex.filter(_._2 % 2 != 0).map(_._1)
res: Array[java.lang.String] = Array(the data i want, and even more data)
String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");
as in javascript:
mydata.match(/'([^']+)'/)[1]
the actual regexp is: /'([^']+)'/
if you use the non greedy modifier (as per another post) it's like this:
mydata.match(/'(.*?)'/)[1]
it is cleaner.
String dataIWant = mydata.split("'")[1];
See Live Demo
In Scala,
val ticks = "'([^']*)'".r
ticks findFirstIn mydata match {
case Some(ticks(inside)) => println(inside)
case _ => println("nothing")
}
for (ticks(inside) <- ticks findAllIn mydata) println(inside) // multiple matches
val Some(ticks(inside)) = ticks findFirstIn mydata // may throw exception
val ticks = ".*'([^']*)'.*".r
val ticks(inside) = mydata // safe, shorter, only gets the first set of ticks
Apache Commons Lang provides a host of helper utilities for the java.lang API, most notably String manipulation methods.
In your case, the start and end substrings are the same, so just call the following function.
StringUtils.substringBetween(String str, String tag)
Gets the String that is nested in between two instances of the same
String.
If the start and the end substrings are different then use the following overloaded method.
StringUtils.substringBetween(String str, String open, String close)
Gets the String that is nested in between two Strings.
If you want all instances of the matching substrings, then use,
StringUtils.substringsBetween(String str, String open, String close)
Searches a String for substrings delimited by a start and end tag,
returning all matching substrings in an array.
For the example in question to get all instances of the matching substring
String[] results = StringUtils.substringsBetween(mydata, "'", "'");
you can use this
i use while loop to store all matches substring in the array if you use
if (matcher.find())
{
System.out.println(matcher.group(1));
}
you will get on matches substring so you can use this to get all matches substring
Matcher m = Pattern.compile("[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+").matcher(text);
// Matcher mat = pattern.matcher(text);
ArrayList<String>matchesEmail = new ArrayList<>();
while (m.find()){
String s = m.group();
if(!matchesEmail.contains(s))
matchesEmail.add(s);
}
Log.d(TAG, "emails: "+matchesEmail);
add apache.commons dependency on your pom.xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
And below code works.
StringUtils.substringBetween(String mydata, String "'", String "'")
Some how the group(1) didnt work for me. I used group(0) to find the url version.
Pattern urlVersionPattern = Pattern.compile("\\/v[0-9][a-z]{0,1}\\/");
Matcher m = urlVersionPattern.matcher(url);
if (m.find()) {
return StringUtils.substringBetween(m.group(0), "/", "/");
}
return "v0";

How to retrieve a value from a list of keys/values separated by pipes?

I have a string like:
String s = "a=xxx|b = yyy|c= zzz"
I am trying to write a function that returns the value corresponding to a given key but it does not work as expected (it returns an empty string):
static String getValueFromKey(String s, String key) {
return s.replaceAll(key + "\\s*=\\s*(.*?)(\\|)?.*", "$1");
}
Test:
static void test() {
String s = "a=xxx|b = yyy|c= zzz";
assertEquals(getValueFromKey(s, "a"), "xxx");
assertEquals(getValueFromKey(s, "b"), "yyy");
assertEquals(getValueFromKey(s, "c"), "zzz");
}
What regex do I need to pass the tests?
Using replaceAll here seems like overkill, because this method will have to iterate over entire String. Instead you could use Matcher and its find method which will stop after matching searched regex (in out case key=value pair).
So maybe use something like:
static String getValueFromKey(String s, String key) {
Matcher m = Pattern.compile(
"(?<=^|\\|)\\s*" + Pattern.quote(key) + "\\b\\s*=\\s*(?<value>[^|]*)")
.matcher(s);
if (m.find())
return m.group("value");
else
return null;// or maybe return empty String "" but that may be misleading
// for values which are really empty Strings
}
You can use this regex for matching:
\W*(\w+)\W*=\W*([^|]*)
RegExDemo
Code:
static void test() {
String s = "a=xxx|b = yyy|c= zzz";
Pattern pattern = Pattern.compile("\\W*(\\w+)\\W*=\\W*([^|]*)");
Matcher matcher = pattern.matcher(s);
while (matcher.find()) {
System.out.println(matcher.group(1) + " :: " + matcher.group(2));
}
}
}
Output:
a :: xxx
b :: yyy
c :: zzz
If you have those string you can use a simple regex like this :
X\s*=\s*(\w*)
Working demo
As Michelle pointed in his comment you if you have apple and pineapple as keys then you can use word boundaries to avoid having a trouble:
\bapple\b\s*=\s*(\w*)
Working demo
According to the question it seems that you only want to change the regex and keep the same code structure. So you have to make sure that your regex match the full pattern, otherwise the string will still contain other data. So even if there are better ways to accomplish this, the answer is:
s.replaceAll(".*?\\b" + key + "\\s*=\\s*(.*?)($|\\|.*)", "$1");
You can test it here.
This is pretty easy to do without regexpressions:
static String getValueFromKey(String s, String key) {
string[] pairs = s.split("|");
for (String p : pairs) {
string[] halves = p.split("=");
if (halves[0].equals(key)) {
return halves[1];
}
}
return "";
}
This code words by splitting the String s on the '|' charachter, creating an array of Strings of the form "key=value". It then splits each of these key-value pairs on the '=' character until it finds key, and returns the associated value.
Is there a specific reason why you need to use a regular expression rather than an approach such as this?

What is the equivalent of Regex-replace-with-function-evaluation in Java 7?

I'm looking for a very simple way of getting the equivalent of something like the following JavaScript code. That is, for each match I would like to call a certain transformation function and use the result as the replacement value.
var res = "Hello World!".replace(/\S+/, function (word) {
// Since this function represents a transformation,
// replacing literal strings (as with replaceAll) are not a viable solution.
return "" + word.length;
})
// res => "5 6"
Only .. in Java. And, preferably as a "single method" or "template" that can be reused.
Your answer is in the Matcher#appendReplacement documentation. Just put your function call in the while loop.
[The appendReplacement method] is intended to be used in a loop together with the appendTail and find methods. The following code, for example, writes one dog two dogs in the yard to the standard-output stream:
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());
Since Java 9 Matcher.replaceAll:
Pattern.compile("\\S+").matcher("Hello World!")
.replaceAll(mr -> "" + mr.group().length());
The parameter freely named mr is a MatchResult, with access methods like mr.group(1) or mr.end() - mr.start().
When allowing Java 8 you can use Lambda-Expressions, to have a JavaScript like replace:
String result = StringReplacer.replace("Hello World!", Pattern.compile("\\S+"), m -> ("" + m.group().length()));
StringReplacer.java:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringReplacer {
public static String replace(String input, Pattern regex, Function<Matcher, String> callback) {
StringBuffer resultString = new StringBuffer();
Matcher regexMatcher = regex.matcher(input);
while (regexMatcher.find()) {
regexMatcher.appendReplacement(resultString, callback.apply(regexMatcher));
}
regexMatcher.appendTail(resultString);
return resultString.toString();
}
}
Source: http://www.whitebyte.info/programming/string-replace-with-callback-in-java-like-in-javascript
Not sure what your precise requirements are but something like this could work:
String res = "";
for (String piece : "hello world".split(" "))
res += Integer.toString(piece.length()) + " ";
Of course there are other ways to write that, and tweaks that can be made depending on requirements (e.g. use a more accurate delimiter than a space).
For a precise implementation of your snippet, you could use e.g. StreamTokenizer with a StringReader and some wrappers to parse out the delimiters and insert them between the counts.

Splitting a string on the double pipe(||) using String.split()

I'm trying to split the string with double pipe(||) being the delimiter.String looks something like this:
String str ="user#email1.com||user#email2.com||user#email3.com";
i'm able to split it using the StringTokeniser.The javadoc says the use of this class is discouraged and instead look at String.split as option.
StringTokenizer token = new StringTokenizer(str, "||");
The above code works fine.But not able to figure out why below string.split function not giving me expected result..
String[] strArry = str.split("\\||");
Where am i going wrong..?
String.split() uses regular expressions. You need to escape the string that you want to use as divider.
Pattern has a method to do this for you, namely Pattern.quote(String s).
String[] split = str.split(Pattern.quote("||"));
You must escape every single | like this str.split("\\|\\|")
try this bellow :
String[] strArry = str.split("\\|\\|");
You can try this too...
String[] splits = str.split("[\\|]+");
Please note that you have to escape the pipe since it has a special meaning in regular expression and the String.split() method expects a regular expression argument.
For this you can follow two different approaches you can follow whichever suites you best:
Approach 1:
By Using String SPLIT functionality
String str = "a||b||c||d";
String[] parts = str.split("\\|\\|");
This will return you an array of different values after the split:
parts[0] = "a"
parts[1] = "b"
parts[2] = "c"
parts[3] = "d"
Approach 2:
By using PATTERN and MATCHER
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String str = "a||b||c||d";
Pattern p = Pattern.compile("\\|\\|");
Matcher m = p.matcher(str);
while (m.find()) {
System.out.println("Found two consecutive pipes at index " + m.start());
}
This will give you the index positions of consecutive pipes:
parts[0] = "a"
parts[1] = "b"
parts[2] = "c"
parts[3] = "d"
Try this
String yourstring="Hello || World";
String[] storiesdetails = yourstring.split("\\|\\|");

Manipulate String by inserting at index

I have a String:
C6H14
What I want it to be is:
C<sub>6</sub>H<sub>14</sub>
So basically I want to add <sub> before a number and </sub> after a number. How can I accomplish this? Keep in mind that the String can be indefinitely long:
X4Y6Z10W4T12
I'm not a java expert, but I'm pretty sure, you can use regular expressions replace function, where the pattern will be:
(\d+)
and replacement string will be:
<sub>$1</sub>
Sorry I'm not 100% sure about the java syntax, but it can be something like:
str = str.replaceAll("(\\d+)", "<sub>$1</sub>");
This method was added in Java 5
here are some more information about regexp in java:
http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
http://www.regular-expressions.info/java.html
http://javamex.com/tutorials/regular_expressions/search_replace.shtml
I would use a Matcher for that:
StringBuffer sb = new StringBuffer();
Matcher m = Pattern.compile("\\d+").matcher(input);
while(m.find()) {
m.appendReplacement(sb,"<sub>$0</sub>");
}
m.appendTail(sb);
String newString = sb.toString();
You will need to construct a new String object for this - there is no way to change a String "in place" (Strings are immutable)
String.replaceAll will do this for you.
str = str.replaceAll( "\\d+", "<sub>$0</sub>" );
is all you need
java.util.Strings are immutable in Java, so you need to build a new String instance. You have to parse the original string (e.g. using regexes) for that. StringBuilder is a good utility for that.
Use Matcher and Pattern classes with searching for pattern:
"\\d+"
After that, find starting and ending indexes and add <sub> and ''
String are immutable, so we cant insert the sub tags in the existing string. So you would need a method that creates a new string. You could use regex, or use a string builder to generate a new string like this:
public String parseString(String input) {
StringBuilder builder = new StringBuilder();
String format = "<sub>%c</sub>";
for(char c:input.toCharArray()) {
if (Character.isDigit(c)) {
builder.append(String.format(format, c));
} else {
builder.append(c);
}
}
return builder.toString();
}

Categories

Resources