Java でパイプ区切り文字列の列数をカウントするには、正規表現が必要です。列データは常に二重引用符で囲まれるか、空になります。
例えば:
"1234"|"Name"||"Some description with ||| in it"|"Last Column"
上記は、「名前」列の後の空列1列を含めて5列としてカウントする必要があります。
ありがとう
これを行う1つの方法は次のとおりです。
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はそれほど堅牢ではありません。たとえば、エスケープされた引用符を処理する予定がある場合は、正規表現を使用することはお勧めしません。
aioobe's answerの式をわずかに改善しました。
int cols = input.replaceAll("\"(?:[^\"\\]+|\\.)*\"|[^|]+", "")
.length() + 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 であり、"\|" でエスケープされている場合は区切り文字です。