I have code that reading a file contains multiple square brackets [] in one line, i will take that value (inside square brackets) and will be replaced by another string. The problem is i just got first square brackets value in the line and the others cannot be handled. This is my code :
if (line.contains("[") && line.contains("]")) {
getindex = getIndexContent(line);
}
And the method to get the index value:
String getIndexContent(String str) {
int startIdx = str.indexOf("[");
int endIdx = str.indexOf("]");
String content = str.substring(startIdx + 1, endIdx);
return content;
}
And this is the file contain square brackets that i read:
var[_ii][_ee] = init_value;
Well, i have got the _ii value but how get the _ee that the second value of square brackets? I just imagine that store in Array, but i don't know how?
Thanks.
you can iterate through your String until you got all
also make life easy by returning all within one method:
List<String> getIndexContent(String str) {
List<String> list = new ArrayList<String>();
while(true){
if(!str.contains("[") && !str.contains("]")){
break;
}
int startIdx = str.indexOf("[");
int endIdx = str.indexOf("]");
String content = str.substring(startIdx + 1, endIdx);
list.add(content);
if(endIdx==str.length()-1){
break;
}
str=str.subString(endIdx+1,str.length());
}
return list;
}
NOTE:
it won't work on nested brackets
You can also do it with regex like this.
Pattern pattern = Pattern.compile("\\[[^\\[.]+?\\]");
String str = "dt = (double[]) obj[i];";
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
System.out.println(matcher.group());
}
You can also get the first and last indices of every matches.
matcher.start() and matcher.end() will return the starting index and the ending index of the current match.
indexOf takes an optional positional argument for the starting point of your search. If you set that to your end index, endIdx, plus one, it will find the second occurrence of the brackets.
int startIdx2 = str.indexOf("[", endIdx + 1);
int endIdx2 = str.indexOf("]", endIdx + 1);
Related
I’m facing a weird problem that I cant resolve for some reason.
If I have this String: “aaaa aa”
And the pattern is: “aa”
So there is 3 places that match that pattern: (aa)(aa)( aa)
I want to change the pattern at specific location (let’s say at the second position) with something else, let’s say this String: “bbb”.
So the final result will be: “aabbb aa”.
What is the simplest way to solve this? Without any special collection or special classes.
One option would be to use a formal regex pattern matcher, and then iterate the input string, looking for aa matches. When we hit the second match, then do a substitution of aa for bb, otherwise just substitute with aa, the original value.
String input = "aaaa aa";
Pattern pattern = Pattern.compile("aa");
Matcher matcher = pattern.matcher(input);
StringBuffer buffer = new StringBuffer();
int num = 0;
while(matcher.find()) {
String replace = num == 1 ? "bbb" : "aa";
matcher.appendReplacement(buffer, replace);
++num;
}
matcher.appendTail(buffer);
System.out.println(buffer.toString());
aabbb aa
The String class has an indexOf method. This method comes in two variants: One where you just specify the needle (the string you want to search), and the method returns the position of the first character in the haystack (the string you are searching) which matches your pattern.
The second variant takes two parameters: The pattern, and the position at which to start.
So, you can do something like this:
void replaceSecondOccurrence(String haystack, String needle, String replacement) {
int occurenceToReplace = 2;
int pos = -1;
while (true) {
pos = haystack.indexOf(needle, pos + 1);
if (pos == -1) {
// There is no second occurence. Just return the haystack.
return haystack;
}
if (--occurenceToReplace == 0) return
haystack.substring(0, pos) +
replacement +
haystack.substring(pos + needle.length());
}
}
So I have something like this
System.out.println(some_string.indexOf("\\s+"));
this gives me -1
but when I do with specific value like \t or space
System.out.println(some_string.indexOf("\t"));
I get the correct index.
Is there any way I can get the index of the first occurrence of whitespace without using split, as my string is very long.
PS - if it helps, here is my requirement. I want the first number in the string which is separated from the rest of the string by a tab or space ,and i am trying to avoid split("\\s+")[0]. The string starts with that number and has a space or tab after the number ends
The point is: indexOf() takes a char, or a string; but not a regular expression.
Thus:
String input = "a\tb";
System.out.println(input);
System.out.println(input.indexOf('\t'));
prints 1 because there is a TAB char at index 1.
System.out.println(input.indexOf("\\s+"));
prints -1 because there is no substring \\s+ in your input value.
In other words: if you want to use the powers of regular expressions, you can't use indexOf(). You would be rather looking towards String.match() for example. But of course - that gives a boolean result; not an index.
If you intend to find the index of the first whitespace, you have to iterate the chars manually, like:
for (int index = 0; index < input.length(); index++) {
if (Character.isWhitespace(input.charAt(index))) {
return index;
}
}
return -1;
Something of this sort might help? Though there are better ways to do this.
class Sample{
public static void main(String[] args) {
String s = "1110 001";
int index = -1;
for(int i = 0; i < s.length(); i++ ){
if(Character.isWhitespace(s.charAt(i))){
index = i;
break;
}
}
System.out.println("Required Index : " + index);
}
}
Well, to find with a regular expression, you'll need to use the regular expression classes.
Pattern pat = Pattern.compile("\\s");
Matcher m = pat.matcher(s);
if ( m.find() ) {
System.out.println( "Found \\s at " + m.start());
}
The find method of the Matcher class locates the pattern in the string for which the matcher was created. If it succeeds, the start() method gives you the index of the first character of the match.
Note that you can compile the pattern only once (even create a constant). You just have to create a Matcher for every string.
There's a string
String str = "ggg;ggg;nnn;nnn;aaa;aaa;xxx;xxx;";
How do I split it into strings like this
"ggg;ggg;"
"nnn;nnn;"
"aaa;aaa;"
"xxx;xxx;"
???????
Using Regex
String input = "ggg;ggg;nnn;nnn;aaa;aaa;xxx;xxx;";
Pattern p = Pattern.compile("([a-z]{3});\\1;");
Matcher m = p.matcher(input);
while (m.find())
// m.group(0) is the result
System.out.println(m.group(0));
Will output
ggg;ggg;
nnn;nnn;
aaa;aaa;
xxx;xxx;
I assume that the you only want to check if the last segment is similar and not every segment that has been read.
If that is not the case then you would probably have to use an ArrayList instead of a Stack.
I also assumed that each segment has the format /([a-z])\1\1/.
If that is not the case either then you should change the if statement with:
(stack.peek().substring(0,index).equals(temp))
public static Stack<String> splitString(String text, char split) {
Stack<String> stack = new Stack<String>();
int index = text.indexOf(split);
while (index != -1) {
String temp = text.substring(0, index);
if (!stack.isEmpty()) {
if (stack.peek().charAt(0) == temp.charAt(0)) {
temp = stack.pop() + split + temp;
}
}
stack.push(temp);
text = text.substring(index + 1);
index = text.indexOf(split);
}
return stack;
}
Split and join them.
public static void main(String[] args) throws Exception {
String data = "ggg;ggg;nnn;nnn;aaa;aaa;xxx;xxx;";
String del = ";";
int splitSize = 2;
StringBuilder sb = new StringBuilder();
for (Iterable<String> iterable : Iterables.partition(Splitter.on(del).split(data), splitSize)) {
sb.append("\"").append(Joiner.on(del).join(iterable)).append(";\"");
}
sb.delete(sb.length()-3, sb.length());
System.out.println(sb.toString());
}
Ref : Split a String at every 3rd comma in Java
Use split with a regex:
String data="ggg;ggg;nnn;nnn;aaa;aaa;xxx;xxx;";
String [] array=data.split("(?<=\\G\\S\\S\\S;\\S\\S\\S);");
S: A non-whitespace character
G: last match/start of string, think of it of a way to skip delimiting if the
previous string matches current one.
?<=:positive look-behind will match semicolon which has string behind it.
Some other answer, that only works given your specific example input.
You see, in your example, there are two similarities:
All patterns seem to have exactly three characters
All patterns occur exactly twice
In other words: if those two properties are really met for all your input, you could avoid splitting - as you know exactly what to find in each position of your string.
Of course, following the other answers for "real" splitting are more flexible; but (theoretically), you could just go forward and do a bunch of substring calls in order to directly access all elements.
I have a question about how to replace String when matched character found. In this case, i read java file that contains variable which marked with underscore. Here the java file:
public int[][] initArray(int rows, int cols, int init_value)
{
int[][] _bb = (int[][])null;
if ((rows > 1) && (cols > 1)) {
_bb = new int[rows][cols];
for (int _ii = 0; _ii < rows; _ii++) {
for (int _ee = 0; _ee < cols; _ee++) {
_bb[_ii][_ee] = init_value;
}
}
} else {
warning("Array length must be greater than zero!");
}
return _bb;
}
All of variable that contain underscore will be replaced with generate string. Well, then this is the code that i have used to read that file and replace matched string:
HashMap<String, String> map = new HashMap<String, String>();
if (line.contains(" _") && line.contains(";")) {
String get = varname(line);
RandomString r = new RandomString();
String[] split = get.split("\\s+");
String gvarname = split[0];
ss = "_"+gvarname;
map.put(ss, "l"+r.generateRandomString());
for(String key: map.keySet()){
if(line.contains(key)){
line = line.replace(key, map.get(key));
}
}
Then, this is a method to get an index of variable name:
String varname(String str){
int startIdx = str.indexOf("_");
int endIdx = str.indexOf(';');
String content = str.substring(startIdx + 1, endIdx);
return content;
}
Actually above code is working and replace some variables name, but some character noted matched when i put space example _bb[_ii] is not working, but _bb[ _ii ] is working. I don't know how, help me!
Thanks
Use regex to recognize the entire variable, here using \b to find word boundaries.
public class Obfuscate {
private static final Pattern VAR_PATTERN = Pattern.compile("\\b_(\\w+)\\b");
private final Map<String, String> renames = new HashMap<>();
public String obfuscate(String sourceCode) {
StringBuffer buf = new StringBuffer(sourceCode.length() + 100);
Matcher m = VAR_PATTERN.matcher(sourceCode);
while (m.find()) {
String var = m.group(1);
String newVar = renames.get(var);
if (newVar == null) {
newVar = randomVar();
renames.put(var, newVar);
}
m.appendReplacement(buf, newVar);
}
m.appendTail(buf);
return buf.toString();
}
}
A map is needed to match the same old variable to the same new name.
A Set<String> of new names might be needed to check that the generated name does not repeat.
Your approach of doing a replaceAll of the same var is fine too, but requires reading all. The method above can be repeated (say per line), hence the map as field.
In your first if-statement you check if the string contains " _" (an underscore with a leading space).
If in the following line of your source-java-file
_bb[_ii][_ee] = init_value;
_bb... is indented with tabulators, <tab>_bb will not match <space>_bb. There is no leading space before _ii and _ee either, so the if returns false.
If you put a space between [ and _ii, you find a match for <space>_ii and your if results in true and executes your replacement code.
If you are sure that there will be no other use of an underscore in your source text other than as a replacement indicator, you can simply remove the space from your if-condition and use line.contains("_") instead.
Btw: Are you sure that you want to check that the line must contain a ; aswell? What if your source text contains a line like while(_xx==true) {?
Also, because of
String[] split = get.split("\\s+");
String gvarname = split[0];
your code is not able to split a line like _bb[_ii][_ee] correctly (and even if it would be, because of split[0] you would only replace the first identifier you found, subsequent ones would be ignored). Your split searches for spaces and the source line doesn't contain any. Again, you could probably change this and split for underscores (this would return an array containing bb[, ii][ and ee]) and then loop every returned array element until you find the first character that can't be part of your variable identifier (e.g. until the first non-alphanumeric character).
An _ plus the part of the array element up to that non-alphanumeric character is then the identifier that you want to replace.
I have a lengthy string and want to break it up into a number of sub-strings so I can display it in a menu as a paragraph rather than a single long line. But I don't want to break it up in the middle of a word (so a break every n characters won't work).
So I want to break the string up by the first occurrence of any of the characters in a String after a certain point (in my case, the characters would be a space and a semi-colon, but they could be anything).
Something like:
String result[] = breakString(baseString, // String
lineLength, // int
breakChars) // String
Consider splitting by the break chars first and then summing the lengths of the segments that result from that split until you reach your line length.
Here is one way. I took "by the first occurrence of any of the characters in a String after a certain point" to mean that the next instance of breakChars after a certain lineLength should be the end of a line. So, breakString("aaabc", 2, "b") would return {"aaab", "c"}.
static String[] breakString(String baseString, int lineLength, String breakChars) {
// find `lineLength` or more characters of the String, until the `breakChars` string
Pattern p = Pattern.compile(".{" + lineLength + ",}?" + Pattern.quote(breakChars));
Matcher m = p.matcher(baseString);
List<String> list = new LinkedList<>();
int index = 0;
while (m.find(index)) {
String s = m.group();
list.add(s);
// find another match starting at the end of the last one
index = m.end();
}
if (index < baseString.length() - 1) {
list.add(baseString.substring(index));
}
return list.toArray(new String[list.size()]);
}