我需要一个正则表达式来计算java中管道分隔字符串中的列数。 列数据将始终用双引号括起来,否则它将为空。
例如:
"1234"|"Name"||"Some description with ||| in it"|"Last Column"
上述内容应计为5列,包括“名称”列后的一列空列。
由于
答案 0 :(得分:8)
这是一种方法:
String input =
"\"1234\"|\"Name\"||\"Some description with ||| in it\"|\"Last Column\"";
// \_______/ \______/\/\_________________________________/ \_____________/
// 1 2 3 4 5
int cols = input.replaceAll("\"[^\"]*\"", "") // remove "..."
.replaceAll("[^|]", "") // remove anything else than |
.length() + 1; // Count the remaining |, add 1
System.out.println(cols); // 5
IMO虽然不是很强大。例如,如果您计划处理转义引号,我建议不要使用正则表达式。
答案 1 :(得分:2)
略微改进aioobe's answer中的表达式:
int cols = input.replaceAll("\"(?:[^\"\\]+|\\.)*\"|[^|]+", "")
.length() + 1;
处理引号中的转义符,并使用单个表达式删除除分隔符以外的所有内容。
答案 2 :(得分:1)
这是我使用的一段正则表达式,它还处理转义引号和转义分隔符。它可能对您的要求(计数列)有些过分,但也许它可以帮助您或将来的其他人进行解析。
(?<=^|(?<!\\)\|)(\".*?(?<=[^\\])\"|.*?(?<!\\(?=\|))(?=")?|)(?=\||$)
and broken down as:
(?<=^|(?<!\\)\|) // look behind to make sure the token starts with the start anchor (first token) or a delimiter (but not an escaped delimiter)
( // start of capture group 1
\".*?(?<=[^\\])\" // a token bounded by quotes
| // OR
.*?(?<!\\(?=\|))(?=")? // a token not bounded by quotes, any characters up to the delimiter (unless escaped)
| // OR
// empty token
) // end of capture group 1
(?=\||$) // look ahead to make sure the token is followed by either a delimiter or the end anchor (last token)
when you actually use it it'll have to be escaped as:
(?<=^|(?<!\\\\)\\|)(\\\".*?(?<=[^\\\\])\\\"|.*?(?<!\\\\(?=\\|))(?=\")?|)(?=\\||$)
这很复杂,但有这种疯狂的方法:如果该行的开头或结尾的列为空,分隔的引号位于奇数位置,行或列开始或结束,我搜索的其他正则表达式将会失效带有转义分隔符和一堆其他边缘情况。
您使用管道作为分隔符这一事实使得此正则表达式更难以阅读/理解。一个提示是你自己看到一个管道“|”,它是正则表达式中的一个条件OR,当它被转义为“\ |”时,它就是你的分隔符。