aa: {
one: "hello",
two: "good",
three: "bye",
four: "tomorrow",
},
"bb": {
"1": "a quick fox",
"2": "a slow bird",
"3": "a smart dog",
"4": "a wilf flowert",
my data look something like above
What i want to select is all the text within "" that is on the right side of the : and that is including the "" marks
what i get is
: ("(.*?)")
but it select the : also which isn't what i want.
If you must use a regular expression, you can try the Matcher.group() method as found here.
public class TestClass {
public static void main(String[] args) {
String input = "aa: {\n" +
" one: \"hello\",\n" +
" two: \"good\",\n" +
" three: \"bye\",\n" +
" four: \"tomorrow\",\n" +
" },\n" +
" \"bb\": {\n" +
" \"1\": \"a quick fox\",\n" +
" \"2\": \"a slow bird\",\n" +
" \"3\": \"a smart dog\",\n" +
" \"4\": \"a wilf flowert\",\n";
// the actual code you need
Pattern pattern = Pattern.compile("(: )(\".+\")");
Matcher match = pattern.matcher(input);
while (match.find()) {
// here you go, only the value without the :
String value = match.group(2);
System.out.println("Found one = " + value);
}
}
}
This results in the following for me:
Found one = "hello"
Found one = "good"
Found one = "bye"
Found one = "tomorrow"
Found one = "a quick fox"
Found one = "a slow bird"
Found one = "a smart dog"
Found one = "a wilf flowert"
Try this:
String p = "(?<=:\\s{0,10})\"[^\"]*\"";
Pattern pat = Pattern.compile(p);
String s =
"aa: {\n" +
" one: \"hello\",\n" +
" two: \"good\",\n" +
" three: \"bye\",\n" +
" four: \"tomorrow\",\n" +
"" +
" },\n" +
" \"bb\": {\n" +
" \"1\": \"a quick fox\",\n" +
" \"2\": \"a slow bird\",\n" +
" \"3\": \"a smart dog\",\n" +
" \"4\": \"a wilf flowert\",\n";
Matcher m = pat.matcher(s);
while (m.find())
System.out.println(m.group());
result:
"hello"
"good"
"bye"
"tomorrow"
"a quick fox"
"a slow bird"
"a smart dog"
"a wilf flowert"
One possible regex is:
(?<=\: )\"*.*\",
(?<=\: ) checks that there is a colon before the prospective string, but does not select it in the regex selection. The rest selects the quotes and the string they surround.
String testData = "test: \"Hello\"";
Pattern p = Pattern.compile("(?<=\\: )\\\"*.*\\\"");
Matcher m = p.matcher(testData);
while (m.find()) {
System.out.println(testData.substring(m.start(), m.end()));
}
I strongly recommend using a JSON parser opposed to a regex, as suggested by fge.
Even though your code is not technically valid JSON, it would be much more efficient and you would avoid reinventing the wheel.
Related
String inputJson = "{\r\n" +
" \"fullName\" : \"Hamo\",\r\n" +
" \"staff\" : false,\r\n" +
" \"supr\" : true,\r\n" +
" \"permissions\" : [ \"Perm1\", \"Perm2\" ],\r\n" +
" \"services\" : [ \"Serv1\", \"Serv2\" ],\r\n" +
" \"authToken\" : \"1234567890abcdefghaijklmnopqrstuvwxyz\",\r\n" +
" \"customerId\" : 12345,\r\n" +
" \"clients\" : [ 1, 3, 8 ],\r\n" +
" \"wts\" : false,\r\n" +
//yyyy-MM-dd
" \"testDate\" : \"1982-09-21\"\r\n" +
"}";
I need to replace authToken value with another string using regex.
This question was edited because it was not asked properly.
Without a JSON class there remains:
inputJson = inputJson.replaceFirst("(\"authToken\"\\s*:\\s*\")[^\"]*\"",
"$1" + authToken + "\"");
This assumes that the authToken does not contain a dollar $.
Apart from using convenient json-editing libraries, you can use regexp:
String inputJson = "{\r\n" +
" \"fullName\" : \"Hamo\",\r\n" +
" \"staff\" : false,\r\n" +
" \"supr\" : true,\r\n" +
" \"permissions\" : [ \"Perm1\", \"Perm2\" ],\r\n" +
" \"services\" : [ \"Serv1\", \"Serv2\" ],\r\n" +
" \"authToken\" : \"1234567890abcdefghaijklmnopqrstuvwxyz\",\r\n" +
" \"customerId\" : 12345,\r\n" +
" \"clients\" : [ 1, 3, 8 ],\r\n" +
" \"wts\" : false,\r\n" +
//yyyy-MM-dd
" \"testDate\" : \"1982-09-21\"\r\n" +
"}";
String desiredAuthToken = "anyAuthTokenYouWant";
inputJson.replaceAll("(\"authToken\"\\s*:\\s*\")\\w*", "$1" + desiredAuthToken);
Here's the explanation:
"(\"authToken\"\\s*:\\s*\")\\w*";
( – start of a first capturing group
\"authToken\" – matches "authToken" string
\\s* – 0 to N whitespaces (including normal spaces, tabulations, etc.)
: – matches a single colon
\\s* – 0 to N whitespaces again
) – end of the capturing group
\\w* – matches 0 to N alphanumeric characters. You may want to replace it with a different regexp, that suits you needs in a better way.
Finally, you are replacing the whole matching expression with "$1" + desiredAuthToken, where $1 is basically the contents of a first capture group. (It is \"authToken\" : \" in this case).
I am attempting to get a value out of a partial JSON payload just using the "split" method. I can only use this method since this API is very limited. I can get my value using Pattern and match APIs..
package com.company;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Main {
public static void main(String[] args) {
// write your code here
String myString = "{\n" +
" \"8\": [\n" +
" {\n" +
" \"TEST\": \"LN17ELJ\",\n" +
" \"ROUTE_UNIQUE_ID_REFERENCE\": \"2172752\",\n" +
" \"ORDER_UNIQUE_ID_REFERENCE\": \"109197634\",\n" +
" \"STATUS\": \"HORLEY\",\n" +
" \"SECONDARY_NAV_CITY\": \"HORLEY\",\n" +
" \"ROUTE\": \"THE STREET 12\",\n";
String myRegexPattern = "\"([ROUTE_UNIQUE_ID_REFERENCE\"]+)\"\\s*:\\s*\"([^\"]+)\",?";
Pattern pattern = Pattern.compile(myRegexPattern);
Matcher matcher = pattern.matcher(myString);
if (matcher.find())
{
System.out.println(matcher.group(2));
} else {
System.out.println("Didn't work!");
}
}
}
However; When I try and using String.split it doesn't work and my value is not in any of the array indexes..
package com.company;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Main {
public static void main(String[] args) {
// write your code here
String myString = "{\n" +
" \"8\": [\n" +
" {\n" +
" \"TEST\": \"LN17ELJ\",\n" +
" \"ROUTE_UNIQUE_ID_REFERENCE\": \"2172752\",\n" +
" \"ORDER_UNIQUE_ID_REFERENCE\": \"109197634\",\n" +
" \"STATUS\": \"HORLEY\",\n" +
" \"SECONDARY_NAV_CITY\": \"HORLEY\",\n" +
" \"ROUTE\": \"THE STREET 12\",\n";
String myRegexPattern = "\"([ROUTE_UNIQUE_ID_REFERENCE\"]+)\"\\s*:\\s*\"([^\"]+)\",?";
String[] newValue = myString.split(myRegexPattern);
for(int i = 0; i < newValue.length; i++) {
if(newValue[i].equals("2172752")) {
System.out.println("IT'S HERE!");
}
}
}
}
What would be the best way to do this? Is there a better way to get ROUTE_UNIQUE_ID_REFERENCE with just using split??
Your regular expression isn't doing what you are expecting. It is not matching "ROUTE_UNIQUE_ID_REFERENCE":"...", but matching any key that starts with any of the letters in ROUTE_UNIQUE_ID_REFERENCE. You could replace it with something like \"ROUTE_UNIQUE_ID_REFERENCE[\"\\s:]+([^\",]+) which will match what you are after in matcher group 1.
The split function doesn't work as you expect. The regular expression you are using in the split is viewed as the delimiter. Thus it is removing the data you are hoping to extract.
Assuming you are looking to get all of the values for ROUTE_UNIQUE_ID_REFERENCE, in the case there is more than one ROUTE_UNIQUE_ID_REFERENCE in your real data, your first example is closer to what you are after.
You need to fix your regular expression and matching group
Use a while loop instead of an if statement to find all the instances
String myRegexPattern = "\"ROUTE_UNIQUE_ID_REFERENCE[\"\\s:]+([^\",]+)";
Pattern pattern = Pattern.compile(myRegexPattern);
Matcher matcher = pattern.matcher(myString);
while (matcher.find()) {
System.out.println(matcher.group(1));
}
I have the following json document:
{
"videoUrl":"",
"available":"true",
"movie":{
"videoUrl":"http..."
},
"account":{
"videoUrl":"http...",
"login":"",
"password":""
}
}
In this json I have a property named videoUrl, I want to get first non empty videoUrl
My regex:
("videoUrl":)("http.+")
But this regex match the following String
"videoUrl" :"http..."},
"account" : {"videoUrl" : "http...","login" : "","password" : ""
What is my way to write Regex that will find first non empty videoUrl with it's value
(Result should be "videoUrl":"http...")
Add (?!,) at the end of the regex, it will make the regex stop at an , without capturing it:
public static void main(String[] args) {
String input = "{ \n" +
" \"videoUrl\":\"\",\n" +
" \"available\":\"true\",\n" +
" \"movie\":{ \n" +
" \"videoUrl\":\"http...\"\n" +
" },\n" +
" \"account\":{ \n" +
" \"videoUrl\":\"http...\",\n" +
" \"login\":\"\",\n" +
" \"password\":\"\"\n" +
" }\n" +
"} ";
Pattern pattern = Pattern.compile("(\"videoUrl\":)(\"http.+\")(?!,)");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
System.out.println(matcher.group()); // "videoUrl":"http..."
}
}
It will be more appropriate to use one of JSON parsers, like Gson or Jackson, instead of regex. Something like:
String jsonStr = "...";
Gson gson = new Gson();
JsonObject json = gson.fromJson(jsonStr, JsonObject.class);
String url = element.get("videoUrl").getAsString();
I need to convert the following string into json format.
Below is the input as well as the expected output for reference.
Input:
Employee Driver Report - EDR
--------------------------------
Employee Nbr: 123480 Employee Type: DI Cat: UPL
Driver License: PP3P30 Plate: ROWP
Part Number: 1006096
Output:
{
"Employee Nbr": "123480",
"Employee Type": "DI",
"Cat": "UPL",
"Driver License": "PP3P30",
"Plate": "ROWP",
"Part Number": "1006096",
}
Sample Code:
Map<String, String> keyValueMap = new HashMap<String, String>();
String[] lines = rawText.split(System.getProperty("line.separator"));
for(String line: lines) {
.......
keyValueMap.put(keyAndValues[i], keyAndValues[i + 1]);
}
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(keyValueMap);
Could you please help me on how to resolve this?
Thanks in advance.
For each line you get, you have to parse it using : and (space) as delimiters.
I'll let you search the correct regex to use and ask for help if needed ;)
You could use an expression like so: ([\w\s]+\s*):\s*([\w]+) (example here) to process the data. This expression assumes that there is no white space within your value parameters.
Thus given the code below:
String source = "Employee Driver Report - EDR\n" +
"--------------------------------\n" +
"Employee Nbr: 123480 Employee Type: DI Cat: UPL\n" +
"Driver License: PP3P30 Plate: ROWP\n" +
"Part Number: 1006096";
String[] lines = source.split("\n");
Pattern p = Pattern.compile("([\\w\\s]+\\s*):\\s*([\\w]+)");
System.out.println("{");
for(int i = 2; i < lines.length; i++)
{
Matcher m = p.matcher(lines[i]);
while(m.find())
{
System.out.println("\"" + m.group(2).trim() + "\":" + "\"" + m.group(1).trim() + "\"");
}
}
System.out.println("}");
You would get something like so:
{
"Employee Nbr":"123480"
"Employee Type":"DI"
"Cat":"UPL"
"Driver License":"PP3P30"
"Plate":"ROWP"
"Part Number":"1006096"
}
EDIT: As per your comment:
String source = "Employee Driver Report - EDR\n" +
"--------------------------------\n" +
"Employee Nbr: 123480 With white space Employee Type: DI Cat: UPL\n" +
"Driver License: PP3P30 Plate: ROWP\n" +
"Part Number: 1006096";
String[] lines = source.split("\n");
Pattern p = Pattern.compile("(Employee Nbr|Employee Type|Cat|Driver License|Plate|Part Number)\\s*:\\s*(.+?)(?:(?=Employee Nbr|Employee Type|Cat|Driver License|Plate|Part Number)|$)");
System.out.println("{");
for(int i = 2; i < lines.length; i++)
{
Matcher m = p.matcher(lines[i]);
while(m.find())
{
System.out.println("\"" + m.group(1).trim() + "\":" + "\"" + m.group(2).trim() + "\"");
}
}
System.out.println("}");
Yields:
{
"Employee Nbr":"123480 With white space"
"Employee Type":"DI"
"Cat":"UPL"
"Driver License":"PP3P30"
"Plate":"ROWP"
"Part Number":"1006096"
}
A description of the updated expression is available here.
I have a string, let's call it output, that's equals the following:
ltm data-group internal str_testclass {
records {
baz {
data "value 1"
}
foobar {
data "value 2"
}
topaz {}
}
type string
}
And I'm trying to extract the substring between the quotes for a given "record" name. So given foobar I want to extract value 2. The substring I want to extract will always come in the form I have prescribed above, after the "record" name, a whitespace, an open bracket, a new line, whitespace, the string data, and then the substring I want to capture is between the quotes from there. The one exception is when there is no value, which will always happen like I have prescribed above with topaz, in which case after the "record" name there will just be an open and closed bracket and I'd just like to get an empty string for this. How could I write a line of Java to capture this? So far I have ......
String myValue = output.replaceAll("(?:foobar\\s{\n\\s*data "([^\"]*)|()})","$1 $2");
But I'm not sure where to go from here.
Let's start extracting "records" structure with following regex ltm\s+data-group\s+internal\s+str_testclass\s*\{\s*records\s*\{\s*(?<records>([^\s}]+\s*\{\s*(data\s*"[^"]*")?\s*\}\s*)*)\}\s*type\s*string\s*\}
Then from "records" group, just find for sucessive match against [^\s}]+\s*\{\s*(?:data\s*"(?<data>[^"]*)")?\s*\}\s*. The "data" group contains what's you're looking for and will be null in "topaz" case.
Java strings:
"ltm\\s+data-group\\s+internal\\s+str_testclass\\s*\\{\\s*records\\s*\\{\\s*(?<records>([^\\s}]+\\s*\\{\\s*(data\\s*\"[^\"]*\")?\\s*\\}\\s*)*)\\}\\s*type\\s*string\\s*\\}"
"[^\\s}]+\\s*\\{\\s*(?:data\\s*\"(?<data>[^\"]*)\")?\\s*\\}\\s*"
Demo:
String input =
"ltm data-group internal str_testclass {\n" +
" records {\n" +
" baz {\n" +
" data \"value 1\"\n" +
" }\n" +
" foobar {\n" +
" data \"value 2\"\n" +
" }\n" +
" topaz {}\n" +
" empty { data \"\"}\n" +
" }\n" +
" type string\n" +
"}";
Pattern language = Pattern.compile("ltm\\s+data-group\\s+internal\\s+str_testclass\\s*\\{\\s*records\\s*\\{\\s*(?<records>([^\\s}]+\\s*\\{\\s*(data\\s*\"[^\"]*\")?\\s*\\}\\s*)*)\\}\\s*type\\s*string\\s*\\}");
Pattern record = Pattern.compile("(?<name>[^\\s}]+)\\s*\\{\\s*(?:data\\s*\"(?<data>[^\"]*)\")?\\s*\\}\\s*");
Matcher lgMatcher = language.matcher(input);
if (lgMatcher.matches()) {
String records = lgMatcher.group();
Matcher rdMatcher = record.matcher(records);
while (rdMatcher.find()) {
System.out.printf("%s:%s%n", rdMatcher.group("name"), rdMatcher.group("data"));
}
} else {
System.err.println("Language not recognized");
}
Output:
baz:value 1
foobar:value 2
topaz:null
empty:
Alernatives: As your parsing a custom language, you can give a try to write an ANTLR grammar or create Groovy DSL.
Your regex shouldn't even compile, because you are not escaping the " inside your regex String, so it is ending your String at the first " inside your regex.
Instead, try this regex:
String regex = key + "\\s\\{\\s*\\n\\s*data\\s*\"([^\"]*)\"";
You can check out how it works here on regex101.
Try something like this getRecord() method where key is the record 'name' you're searching for, e.g. foobar, and the input is the string you want to search through.
public static void main(String[] args) {
String input = "ltm data-group internal str_testclass { \n" +
" records { \n" +
" baz { \n" +
" data \"value 1\" \n" +
" } \n" +
" foobar { \n" +
" data \"value 2\" \n" +
" }\n" +
" topaz {}\n" +
" } \n" +
" type string \n" +
"}";
String bazValue = getRecord("baz", input);
String foobarValue = getRecord("foobar", input);
String topazValue = getRecord("topaz", input);
System.out.println("Record data value for 'baz' is '" + bazValue + "'");
System.out.println("Record data value for 'foobar' is '" + foobarValue + "'");
System.out.println("Record data value for 'topaz' is '" + topazValue + "'");
}
private static String getRecord(String key, String input) {
String regex = key + "\\s\\{\\s*\\n\\s*data\\s*\"([^\"]*)\"";
final Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
//if we find a record with data return it
return matcher.group(1);
} else {
//else see if the key exists with empty {}
final Pattern keyPattern = Pattern.compile(key);
Matcher keyMatcher = keyPattern.matcher(input);
if (keyMatcher.find()) {
//return empty string if key exists with empty {}
return "";
} else {
//else handle error, throw exception, etc.
System.err.println("Record not found for key: " + key);
throw new RuntimeException("Record not found for key: " + key);
}
}
}
Output:
Record data value for 'baz' is 'value 1'
Record data value for 'foobar' is 'value 2'
Record data value for 'topaz' is ''
You could try
(?:foobar\s{\s*data "(.*)")
I think the replaceAll() isn't necessary here. Would something like this work:
String var1 = "foobar";
String regex = '(?:' + var1 + '\s{\n\s*data "([^"]*)")';
You can then use this as your regex to pass into your pattern and matcher to find the substring.
You can simple transform this into a function so that you can pass variables into it for your search string:
public static void SearchString(String str)
{
String regex = '(?:' + str + '\s{\n\s*data "([^"]*)")';
}