接收管道分离参数,需要对其进行标记化;但管道可以用\ |进行转义表明它不是分离器,而是令牌的一部分。我知道Java编译器使用我们在字符串文字中“和转义引号”的字符串来执行此操作。
但不确定一个好的效用函数/算法来标记这样的字符串。输出将是字符串列表。
示例输入1:"jk|g4"
,输出:"jk" , "g4"
(包含2个字符串的列表)
示例输入2:"j\|k|g4|b"
,输出:"j|k" , "g4", "b"
(包含3个字符串和文字管道的列表)
尝试使用String.indexOf("|")
,然后检查前一个字符是否为\ ...但是有错误并且想要确定:是否有更简单的方法?正则表达式?
这就是我所拥有的:
import java.util.ArrayList;
import java.util.List;
public class PasrePipes {
public static void main(String[] args) {
String in = "j\\|k|g4|b";
{
String[] ex = { "j|k", "g4", "b" };
tst(in, ex);
}
in = "j|k|g4|b";
{
String[] ex = { "j", "k", "g4", "b" };
tst(in, ex);
}
}
private static void tst(String in, String[] ex) {
System.out.println("----\n" + in);
List<String> toks = parse(in);
if (toks.size() != ex.length) {
System.out.println("size mismatch, got :" + toks.size() + " exp " + ex.length);
}
for (int i = 0; i < ex.length; i++) {
if (toks.size() > i) {
String n = toks.get(i);
if (!ex[i].equals(n)) {
System.out.println(" mismatch :" + i + ", got :" + n + "; exp :" + ex[i]);
} else {
System.out.println(" okay :" + i + "; exp :" + ex[i]);
}
}
}
System.out.println("--");
}
private static List<String> parse(String in) {
List<String> tokens = new ArrayList<String>();
int i = in.indexOf('|');
int old = 0;
while (i > -1) {
if (i > 0) {
if (in.charAt(i - 1) == '\\') {
i = in.indexOf('|', i + 1);
continue;
}
}
String s = in.substring(old, i);
s.replace("\\|", "|");
tokens.add(s);
old = i + 1;
i = in.indexOf('|', i + 1);
}
if(i > 0 && i < (in.length() - 1)) {
String s = in.substring(i + 1);
s.replace("\\|", "|");
tokens.add(s);
}
return tokens;
}
}
答案 0 :(得分:4)
无法同时使用单个正则表达式语句进行拆分和替换。但你可以使用负面看法分开:
(?<!\\)[\|]
然后将\|
替换为|
String value = "j\\|k|g4|b";
String[] split = value.split("(?<!\\\\)(\\|)");
for(int i = 0; i < split.length; i++){
split[i] = split[i].replaceAll("(\\\\\\|)", "\\|");
System.out.println(split[i]);
}
输出:
j|k
g4
b
<强>更新强>
请注意,如果您在管道前直接转出斜杠,这将无效。
String value = "j\\\\|k|g4|b";
...
输出:
j\|k
g4
b
期望的输出:
j\
k
g4
b
因为Java不支持可变长度的后视,所以无法在分隔符上拆分字符串。但是,您可以使用Pattern
和Matcher
来匹配每个字段,并在分隔符之前使用偶数个斜杠。
String value = "j\\|k|g4|b|kjbk\\\\\\|\\ml|jbkjbjk\\\\\\\\|k\\jb\\k\\\\\\j|m\\\\\\|\\\\kb";
Pattern pattern = Pattern.compile("(([^\\\\](\\\\\\\\)*\\\\\\|)|([^\\|]))+");
Matcher matcher = pattern.matcher(value);
List<String> fields = new ArrayList<String>();
while(matcher.find()){
String field = matcher.group().replaceAll("(\\\\\\|)", "\\|");
fields.add(field);
System.out.println(field);
}
输出:
j|k
g4
b
kjbk\\|\ml
jbkjbjk\\\\
k\jb\k\\\j
m\\|\\kb
答案 1 :(得分:2)
如果速度不是一件大事,你可以尝试遵循pidgin方式:
//replaces all escaped pipes to a temporary replacement
string = string.replaceAll("\\\\\\|", "tmpReplacement");
//iterate through all parts of the string which is divided by a pipe
for(String str : string.split("\\|"))
{
str = str.replaceAll("tmpReplacement" , "\\|"/*or how you need it*/);
//now you can use str; str is each part of the variable string, which has not been escaped
}
答案 2 :(得分:2)
这可以通过正则表达式完成(如Syon所示),但它看起来太复杂且容易出错。我发现这个简单的功能是一个更好的解决方案:
/*
* Parses a delimited string with an escape character
*/
public static List<String> parse(String s, char delimeter, char escape){
List<String> result = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
boolean escaped = false;
for(char ch : s.toCharArray()){
if(escaped){
sb.append(ch);
escaped = false;
}
else {
if (ch == escape){
escaped = true;
}
else if(ch == delimeter){
result.add(sb.toString());
sb.setLength(0);
}
else{
sb.append(ch);
}
}
}
result.add(sb.toString());
return result;
}
你这样称呼它:
parse("j\\|k|g4|b", '|', '\\') // --> [ "j|k", "g4", "b" ]