I'm working with a CSV file that in places, has multiple commas and pound signs. My question is about how to remove the multiple commas and the pound signs, while leaving a single comma between fields.
The part of this task I am on is, using only java and no external libraries to sort through the csv file sort the array by price. I am to input a number as an input parameter and return that number of rows, ordered by price.
What I have currently is around 1000 lines of data that looks like this:
18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,,£307018.48,
I need to remove the double commas and the pound sign, but for the life of me haven't been able to get it to work.
This is the line I am using for the regex.
String currentLine = line.replaceAll("[,{2}|£]", "");
This outputs a line which looks like this:
100086 Norway Maple WayMadelleGeorgeotmgeorgeotrr#hao13.com417175.60
A larger chunk of the code looks like this and by no means is it nearly finished:
public String[] getTopProperties(int n){
String[] properties = new String[n];
String file = "data.csv";
String line = "";
String splitBy = ",";
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
while ((line = br.readLine()) != null) {
String currentLine = line.replaceAll("[,{2}|£]", "");
System.out.println("Current line is: " + currentLine);
String[] user = currentLine.split(splitBy);
}
} catch (IOException e) {
e.printStackTrace();
}
return properties;
}
Issue is it's now removed all the commas and where the price and double commas used to be, they now connect.
Could use some help finding some regex that keeps a single comma between each field, as well as removing the pound sign.
You could simplify this by parsing the CSV file into a 2D array and ignoring the empty column which results from the double comma. Then parsing the currency column is a snap: just ignore the first character.
In your regex .replaceAll("[,{2}|£]", ""); the square-brackets creates a character class, so this means "replace any characters ,, {, 2, }, |, or £ with nothing".
What you really want is to replace the sequence ,,£ with a single comma, which would be .replaceAll(",,£", ",")
In java script this would be...
var line="18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,,£307018.48,";
console.log(' original line: ' + line);
console.log('replacement line: ' + line.replace(/,,£/, ","));
update
Converting this to Java as a stand-alone test program to demonstrate that this does work, I get the following:
public class so50419207
{
public static void main(String... args)
{
String input = "18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,,£307018.48,";
String replaced = input.replace(",,£", ",");
System.out.println("original string: " + input);
System.out.println("replaced string: " + replaced);
}
}
Running this...
$ javac so50419207.java ; java so50419207
original string: 18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,,£307018.48,
replaced string: 18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,307018.48,
Tried the regex (,,)(£)? and tested it in ideone :
Please find the code below:
import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
final String regex = "(,,)(£)?";
final String string = "18,,5 Ramsey Lane,,See,Amerighi,,samerighih#trellian.com,,£307018.48,,\n"
+ "18,,5 Ramsey Lane,,See,Amerighi,,samerighih#trellian.com,,£307018.48,,\n"
+ "18,5 Ramsey Lane,,See,Amerighi,,samerighih#trellian.com,,£307018.48,,\n"
+ "18,,5 Ramsey Lane,,See,Amerighi,,samerighih#trellian.com,,£307018.48,,";
final String subst = ",";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);
// The substituted value will be contained in the result variable
final String result = matcher.replaceAll(subst);
System.out.println("Substitution result: " + result);
}
}
Output:
Substitution result: 18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,307018.48,
18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,307018.48,
18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,307018.48,
18,5 Ramsey Lane,See,Amerighi,samerighih#trellian.com,307018.48,
Related
Hi I have a csv file with an error in it.so i want it to correct with regular expression, some of the fields contain line break, Example as below
"AHLR150","CDS","-1","MDCPBusinessRelationshipID",,,"Investigating","1600 Amphitheatre Pkwy
California",,"Mountain View",,"United States",,"California",,,"94043-1351","9958"
the above two lines should be in one line
"AHLR150","CDS","-1","MDCPBusinessRelationshipID",,,"Investigating","1600 Amphitheatre PkwyCalifornia",,"Mountain View",,"United States",,"California",,,"94043-1351","9958"
I tried to use the below regex but it didnt help me
%s/\\([^\"]\\)\\n/\\1/
Try this:
public static void main(String[] args) {
String input = "\"AHLR150\",\"CDS\",\"-1\",\"MDCPBusinessRelationshipID\","
+ ",,\"Investigating\",\"1600 Amphitheatre Pkwy\n"
+ "California\",,\"Mountain View\",,\"United\n"
+ "States\",,\"California\",,,\"94043-1351\",\"9958\"\n";
Matcher matcher = Pattern.compile("\"([^\"]*[\n\r].*?)\"").matcher(input);
Pattern patternRemoveLineBreak = Pattern.compile("[\n\r]");
String result = input;
while(matcher.find()) {
String quoteWithLineBreak = matcher.group(1);
String quoteNoLineBreaks = patternRemoveLineBreak.matcher(quoteWithLineBreak).replaceAll(" ");
result = result.replaceFirst(quoteWithLineBreak, quoteNoLineBreaks);
}
//Output
System.out.println(result);
}
Output:
"AHLR150","CDS","-1","MDCPBusinessRelationshipID",,,"Investigating","1600 Amphitheatre Pkwy California",,"Mountain View",,"United States",,"California",,,"94043-1351","9958"
Create a RegEx surrounding the text you want to keep by parentheses and that will create a group of matched characters. Then replace the string using the group index to compose as you wish.
String test = "\"AHLR150\",\"CDS\",\"-1\",\"MDCPBusinessRelationshipID\","
+ ",,\"Investigating\",\"1600 Amphitheatre Pkwy\n"
+ "California\",,\"Mountain View\",,\"United\n"
+ "States\",,\"California\",,,\"94043-1351\",\"9958\"\n";
System.out.println(test.replaceAll("(\"[^\"]*)\n([^\"]*\")", "$1$2"));
So when we replace the matching string ("United\nStates") by $1$2 we are removing the line break because it not belongs to any group:
$1 => the first group (\"[^\"]*) that will match "United
$2 => the second group ([^\"]*\")" that will match States"
Based on this you can try with:
/\r?\n|\r/
I checked it here and seems to be fine
I need to split a string in Java (first remove whitespaces between quotes and then split at whitespaces.)
"abc test=\"x y z\" magic=\" hello \" hola"
becomes:
firstly:
"abc test=\"xyz\" magic=\"hello\" hola"
and then:
abc
test="xyz"
magic="hello"
hola
Scenario :
I am getting a string something like above from input and I want to break it into parts as above. One way to approach was first remove the spaces between quotes and then split at spaces. Also string before quotes complicates it. Second one was split at spaces but not if inside quote and then remove spaces from individual split. I tried capturing quotes with "\"([^\"]+)\"" but I'm not able to capture just the spaces inside quotes. I tried some more but no luck.
We can do this using a formal pattern matcher. The secret sauce of the answer below is to use the not-much-used Matcher#appendReplacement method. We pause at each match, and then append a custom replacement of anything appearing inside two pairs of quotes. The custom method removeSpaces() strips all whitespace from each quoted term.
public static String removeSpaces(String input) {
return input.replaceAll("\\s+", "");
}
String input = "abc test=\"x y z\" magic=\" hello \" hola";
Pattern p = Pattern.compile("\"(.*?)\"");
Matcher m = p.matcher(input);
StringBuffer sb = new StringBuffer("");
while (m.find()) {
m.appendReplacement(sb, "\"" + removeSpaces(m.group(1)) + "\"");
}
m.appendTail(sb);
String[] parts = sb.toString().split("\\s+");
for (String part : parts) {
System.out.println(part);
}
abc
test="xyz"
magic="hello"
hola
Demo
The big caveat here, as the above comments hinted at, is that we are really using a regex engine as a rudimentary parser. To see where my solution would fail fast, just remove one of the quotes by accident from a quoted term. But, if you are sure you input is well formed as you have showed us, this answer might work for you.
I wanted to mention the java 9's Matcher.replaceAll lambda extension:
// Find quoted strings and remove there whitespace:
s = Pattern.compile("\"[^\"]*\"").matcher(s)
.replaceAll(mr -> mr.group().replaceAll("\\s", ""));
// Turn the remaining whitespace in a comma and brace all.
s = '{' + s.trim().replaceAll("\\s+", ", ") + '}';
Probably the other answer is better but still I have written it so I will post it here ;) It takes a different approach
public static void main(String[] args) {
String test="abc test=\"x y z\" magic=\" hello \" hola";
Pattern pattern = Pattern.compile("([^\\\"]+=\\\"[^\\\"]+\\\" )");
Matcher matcher = pattern.matcher(test);
int lastIndex=0;
while(matcher.find()) {
String[] parts=matcher.group(0).trim().split("=");
boolean newLine=false;
for (String string : parts[0].split("\\s+")) {
if(newLine)
System.out.println();
newLine=true;
System.out.print(string);
}
System.out.println("="+parts[1].replaceAll("\\s",""));
lastIndex=matcher.end();
}
System.out.println(test.substring(lastIndex).trim());
}
Result is
abc
test="xyz"
magic="hello"
hola
It sounds like you want to write a basic parser/Tokenizer. My bet is that after you make something that can deal with pretty printing in this structure, you will soon want to start validating that there arn't any mis-matching "'s.
But in essence, you have a few stages for this particular problem, and Java has a built in tokenizer that can prove useful.
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
public class Q50151376{
private static class Whitespace{
Whitespace(){ }
#Override
public String toString() {
return "\n";
}
}
private static class QuotedString {
public final String string;
QuotedString(String string) {
this.string = "\"" + string.trim() + "\"";
}
#Override
public String toString() {
return string;
}
}
public static void main(String[] args) {
String test = "abc test=\"x y z\" magic=\" hello \" hola";
StringTokenizer tokenizer = new StringTokenizer(test, "\"");
boolean inQuotes = false;
List<Object> out = new LinkedList<>();
while (tokenizer.hasMoreTokens()) {
final String token = tokenizer.nextToken();
if (inQuotes) {
out.add(new QuotedString(token));
} else {
out.addAll(TokenizeWhitespace(token));
}
inQuotes = !inQuotes;
}
System.out.println(joinAsStrings(out));
}
private static String joinAsStrings(List<Object> out) {
return out.stream()
.map(Object::toString)
.collect(Collectors.joining());
}
public static List<Object> TokenizeWhitespace(String in){
List<Object> out = new LinkedList<>();
StringTokenizer tokenizer = new StringTokenizer(in, " ", true);
boolean ignoreWhitespace = false;
while (tokenizer.hasMoreTokens()){
String token = tokenizer.nextToken();
boolean whitespace = token.equals(" ");
if(!whitespace){
out.add(token);
ignoreWhitespace = false;
} else if(!ignoreWhitespace) {
out.add(new Whitespace());
ignoreWhitespace = true;
}
}
return out;
}
}
I need to find the length of my string "பாரதீய ஜனதா இளைஞர் அணி தலைவர் அனுராக்சிங் தாகூர் எம்.பி. நேற்று தேர்தல் ஆணையர் வி.சம்பத்". I got the string length as 45 but i expect the string length to be 59. Here i need to add the regular expression condition for spaces and dot (.). My code
import java.util.*;
import java.lang.*;
import java.util.regex.*;
class UnicodeLength
{
public static void main (String[] args)
{
String s="பாரதீய ஜனதா இளைஞர் அணி தலைவர் அனுராக்சிங் தாகூர் எம்பி நேற்று தேர்தல் ஆணையர் விசம்பத்";
List<String> characters=new ArrayList<String>();
Pattern pat = Pattern.compile("\\p{L}\\p{M}*");
Matcher matcher = pat.matcher(s);
while (matcher.find()) {
characters.add(matcher.group());
}
// Test if we have the right characters and length
System.out.println(characters);
System.out.println("String length: " + characters.size());
}
}
The code below worked for me. There were three issues that I fixed:
I added a check for spaces to your regular expression.
I added a check for punctuation to your regular expression.
I pasted the string from your comment into the string in your code. They weren't the same!
Here's the code:
public static void main(String[] args) {
String s = "பாரதீய ஜனதா இளைஞர் அணி தலைவர் அனுராக்சிங் தாகூர் எம்.பி. நேற்று தேர்தல் ஆணையர் வி.சம்பத்";
List<String> characters = new ArrayList<String>();
Pattern pat = Pattern.compile("\\p{P}|\\p{L}\\p{M}*| ");
Matcher matcher = pat.matcher(s);
while (matcher.find()) {
characters.add(matcher.group());
}
// Test if we have the right characters and length
int i = 1;
for (String character : characters) {
System.out.println(String.format("%d = [%s]", i++, character));
}
System.out.println("Characters Size: " + characters.size());
}
It's probably worth pointing out that your code is remarkably similar to the solution for this SO. One comment on that solution in particular led me to discover the missing check for punctuation in your code and allowed me to notice that the string from your comment didn't match the string in your code.
I want to add Two java JSON String manually , so for this i need to remove "}" and replace it with comma "," of first JSON String and remove the first "{" of the second JSON String .
This is my program
import java.util.Map;
import org.codehaus.jackson.type.TypeReference;
public class Hi {
private static JsonHelper jsonHelper = JsonHelper.getInstance();
public static void main(String[] args) throws Exception {
Map<String, Tracker> allCusts = null;
String A = "{\"user5\":{\"Iden\":4,\"Num\":1},\"user2\":{\"Iden\":5,\"Num\":1}}";
String B = "{\"user1\":{\"Iden\":4,\"Num\":1},\"user3\":{\"Iden\":6,\"Num\":1},\"user2\":{\"Iden\":5,\"Num\":1}}";
String totalString = A + B;
if (null != totalString) {
allCusts = (Map<String, Tracker>) jsonHelper.toObject(
totalString, new TypeReference<Map<String, Tracker>>() {
});
}
System.out.println(allCusts);
}
}
When adding two Strings A + B
I want to remove the last character of "}" in A and replace it with "," and remove the FIrst character of "{" in B .
SO this should it look like .
String A = "{\"user5\":{\"Iden\":4,\"Num\":1},\"user2\":{\"Iden\":5,\"Num\":1},";
String B = "\"user1\":{\"Iden\":4,\"Num\":1},\"user3\":{\"Iden\":6,\"Num\":1},\"user2\":{\"Iden\":5,\"Num\":1}}";
I have tried
String Astr = A.replace(A.substring(A.length()-1), ",");
String Bstr = B.replaceFirst("{", "");
String totalString = Astr + Bstr ;
With this i was getting
Exception in thread "main" java.util.regex.PatternSyntaxException: Illegal repetition
please suggest .
{ is a control character for Regular Expressions, and since replaceFirst takes a string representation of a Regular Expression as its first argument, you need to escape the { so it's not treated as a control character:
String Bstr = B.replaceFirst("\\{", "");
I would say that using the replace methods is really overkill here since you're just trying to chop a character off of either end of a string. This should work just as well:
String totalString = A.substring(0, A.length()-1) + "," + B.substring(1);
Of course, regex doesn't look like a very good tool for this. But the following seem to work:
String str = "{..{...}..}}";
str = str.replaceFirst("\\{", "");
str = str.replaceFirst("}$", ",");
System.out.println(str);
Output:
..{...}..},
Some issues in your first two statements. Add 0 as start index in substring method and leave with that. Put \\ as escape char in matching pattern and ut a , in second statement as replacement value.
String Astr = A.substring(0, A.length()-1);//truncate the ending `}`
String Bstr = B.replaceFirst("\\{", ",");//replaces first '{` with a ','
String totalString = Astr + Bstr ;
Please note: There are better ways, but I am just trying to correct your statements.
I want to parse a line from a CSV(comma separated) file, something like this:
Bosh,Mark,mark#gmail.com,"3, Institute","83, 1, 2",1,21
I have to parse the file, and instead of the commas between the apostrophes I wanna have ';', like this:
Bosh,Mark,mark#gmail.com,"3; Institute","83; 1; 2",1,21
I use the following Java code but it doesn't parse it well:
Pattern regex = Pattern.compile("(\"[^\\]]*\")");
Matcher matcher = regex.matcher(line);
if (matcher.find()) {
String replacedMatch = matcher.group();
String gr1 = matcher.group(1);
gr1.trim();
replacedMatch = replacedMatch.replace(",", ";");
line = line.replace(matcher.group(), replacedMatch);
}
the output is:
Bosh,Mark,mark#gmail.com,"3; Institute";"83; 1; 2",1,21
anyone have any idea how to fix this?
This is my solution to replace , inside quote to ;. It assumes that if " were to appear in a quoted string, then it is escaped by another ". This property ensures that counting from start to the current character, if the number of quotes " is odd, then that character is inside a quoted string.
// Test string, with the tricky case """", which resolves to
// a length 1 string of single quote "
String line = "Bosh,\"\"\"\",mark#gmail.com,\"3, Institute\",\"83, 1, 2\",1,21";
Pattern pattern = Pattern.compile("\"[^\"]*\"");
Matcher matcher = pattern.matcher(line);
int start = 0;
StringBuilder output = new StringBuilder();
while (matcher.find()) {
// System.out.println(m.group() + "\n " + m.start() + " " + m.end());
output
.append(line.substring(start, matcher.start())) // Append unrelated contents
.append(matcher.group().replaceAll(",", ";")); // Append replaced string
start = matcher.end();
}
output.append(line.substring(start)); // Append the rest of unrelated contents
// System.out.println(output);
Although I cannot find any case that will fail the method of replace the matched group like you did in line = line.replace(matcher.group(), replacedMatch);, I feel safer to rebuild the string from scratch.
Here's a way:
import java.util.regex.*;
class Main {
public static void main(String[] args) {
String in = "Bosh,Mark,mark#gmail.com,\"3, \"\" Institute\",\"83, 1, 2\",1,21";
String regex = "[^,\"\r\n]+|\"(\"\"|[^\"])*\"";
Matcher matcher = Pattern.compile(regex).matcher(in);
StringBuilder out = new StringBuilder();
while(matcher.find()) {
out.append(matcher.group().replace(',', ';')).append(',');
}
out.deleteCharAt(out.length() - 1);
System.out.println(in + "\n" + out);
}
}
which will print:
Bosh,Mark,mark#gmail.com,"3, "" Institute","83, 1, 2",1,21
Bosh,Mark,mark#gmail.com,"3; "" Institute","83; 1; 2",1,21
Tested on Ideone: http://ideone.com/fCgh7
Here is the what you need
String line = "Bosh,Mark,mark#gmail.com,\"3, Institute\",\"83, 1, 2\",1,21";
Pattern regex = Pattern.compile("(\"[^\"]*\")");
Matcher matcher = regex.matcher(line);
while(matcher.find()){
String replacedMatch = matcher.group();
String gr1 = matcher.group(1);
gr1.trim();
replacedMatch = replacedMatch.replace(",", ";");
line = line.replace(matcher.group(), replacedMatch);
}
line will have value you needed.
Have you tried to make the RegExp lazy?
Another idea: inside the [] you should use a " too. If you do that, you should have the expected output with global flag set.
Your regex is faulty. Why would you want to make sure there are no ] within the "..." expression? You'd rather make the regex reluctant (default is eager, which means it catches as much as it can).
"(\"[^\\]]*\")"
should be
"(\"[^\"]*\")"
But nhadtdh is right, you should use a proper CSV library to parse it and replace , to ; in the values the parser returns.
I'm sure you'll find a parser when googling "Java CSV parser".
Shouldn't your regex be ("[^"]*") instead? In other words, your first line should be:
Pattern regex = Pattern.compile("(\"[^\"]*\")");
Of course, this is assuming you can't have quotes in the quoted values of your input line.