У меня есть строка, образованная из имен (без пробелов), разделенных точками. Каждый токен (после периода) может начинаться с [a-zA-Z_]
или [
(и заканчивается на ]
) или $
(и заканчивается на $
).
Примеры:
Поэтому мне нужно разделить строку по периоду, но в последних двух примерах я abc.def
разбить 4.45
(или abc.def
). Все, что окружено $
не должно быть разделено.
Для двух последних примеров я просто хочу создать такой массив:
или
Я попытался использовать регулярное выражение, но я совершенно неправ.
Мне просто сообщили, что после закрытия $
может быть другая строка, окруженная <
и >
которая может снова содержать точки, которые я не должен разделять:
House.Car.$abc.def$<ghi.jk>.[0].bla
И мне нужно это сделать так:
House
Car
$abc.def$<ghi.jk>
[0]
bla
Спасибо за вашу помощь.
Вам лучше собирать результаты, "ходя" строку в соответствии с .find()
:
// Note the alternation
private static final Pattern PATTERN
= Pattern.compile("\\$[^.$]+(\\.[^.$]+)*\\$|[^.]+");
//
public List<String> matchesForInput(final String input)
{
final Matcher m = PATTERN.matcher(input);
final List<String> matches = new ArrayList<>();
while (m.find())
matches.add(m.group());
return matches;
}
PATTERN
постоянной? О, и это должно быть `PATTERN = Pattern.compile (" \\ ...] + ").
Matcher
ов, сколько захочу;)
Если параметр regex не используется, вы можете написать свой собственный синтаксический анализатор, который будет перебирать один раз по всем символам в вашей строке, проверяя, находится ли символ внутри $...$
, [...]
или <...>
.
.
то вам нужно просто добавить его в токен, который вы строите, как любой обычный персонаж,.
но он находится в ранее упомянутых "областях"..
и вы находитесь за пределами этих областей, вам нужно разделить его, что означает добавление в текущий момент токена сборки для получения и очистки его для следующего токена.Такой парсер может выглядеть так
public static List<String> parse(String input){
//list which will hold retuned tokens
List<String> tokens = new ArrayList<>();
// flags representing if currently tested character is inside some of
// special areas
// (at start we are outside of these areas so hey are set to false)
boolean insideDolar = false; // $...$
boolean insideSquareBrackets = false; // [...]
boolean insideAgleBrackets =false; // <...>
// we need some buffer to build tokens, StringBuilder is excellent here
StringBuilder sb = new StringBuilder();
// now lets iterate over all characters and decide if we need to add them
// to token or just add token to result list
for (char ch : input.toCharArray()){
// lets update in which area are we
// finding $ means that we either start or end '$...$' area so
// simple negation of flag is enough to update its status
if (ch == '$') insideDolar = !insideDolar;
//updating rest of flags seems pretty obvious
else if (ch == '[') insideSquareBrackets = true;
else if (ch == ']') insideSquareBrackets = false;
else if (ch == '<') insideAgleBrackets = true;
else if (ch == '>') insideAgleBrackets = false;
// So now we know in which area we are, so lets handle special cases
// if we are handling no dot
// OR we are handling dot but we are inside either of areas we need
// to just add it to token (append it to StringBuilder)
if (ch != '.' || insideAgleBrackets|| insideDolar || insideSquareBrackets ){
sb.append(ch);
}else{// other case means that we are handling dot outside of special
// areas where dots are not separators, so now they represents place
// to split which means that we don't add it to token, but
// add value from buffer (current token) to results and reset buffer
// for next token
tokens.add(sb.toString());
sb.delete(0, sb.length());
}
}
// also since we only add value held in buffer to list of tokens when we
// find dot on which we split, there is high chance that we will not add
// last token to result, because there is no dot after it, so we need to
// do it manually after iterating over all characters
if (sb.length()>0)//non empty token needs to be added to result
tokens.add(sb.toString());
return tokens;
}
и вы можете использовать его как
String input = "House.Car2.$abc.def$<ghi.jk>.[0]";
for (String s: parse(input))
System.out.println(s);
вывод:
House
Car2
$abc.def$<ghi.jk>
[0]
Я считаю, что с помощью Pattern/Matcher будет проще. Сырое регулярное выражение:
\$[^$]+\$|\[[^\]]+\]|[^.]+
В коде:
String s = "House.Car2.$4.45$.[0]";
Pattern pattern = Pattern.compile("\\$[^$]+\\$|\\[[^\\]]+\\]|[^.]+");
Matcher matcher = pattern.matcher(s);
while (matcher.find()) {
System.out.println(matcher.group());
}
Вывод:
House
Car2
$4.45$
[0]
$
s.
replaceAll
. Я отредактирую
$
с выхода ??