所以,我有一个字符串。大多数情况下,如果字符串中包含方括号,则会发生不好的事情。但是,在少数情况下,必须保留括号。需要保留的这些括号由特定前缀标识。例如,如果字符串是:
apple] [s [pears]前缀:[oranges] lemons] persimmons [pea [ches ap] ricots [] [[]]] []
我想把它变成:
苹果梨前缀:[橙子]柠檬柿子桃子杏子
我想出了一个Rube Goldberg混乱的解决方案,看起来像这样:
public class Debracketizer
{
public static void main( String[] args )
{
String orig = "apples [pears] prefix:[oranges] lemons ]persimmons[ pea[ches ap]ricots";
String result = debracketize(orig);
System.out.println(result);
}
private static void debracketize( String orig )
{
String result1 = replaceAll(orig,
Pattern.compile("\\["),
"",
".*prefix:$");
String result2 = replaceAll(result1,
Pattern.compile("\\]"),
"",
".*prefix:\\[[^\\]]+$");
System.out.println(result2);
}
private static String replaceAll( String orig, Pattern pattern,
String replacement, String skipPattern )
{
String quotedReplacement = Matcher.quoteReplacement(replacement);
Matcher matcher = pattern.matcher(orig);
StringBuffer sb = new StringBuffer();
while( matcher.find() )
{
String resultSoFar = orig.substring(0, matcher.start());
if (resultSoFar.matches(skipPattern)) {
matcher.appendReplacement(sb, matcher.group());
} else {
matcher.appendReplacement(sb, quotedReplacement);
}
}
matcher.appendTail(sb);
return sb.toString();
}
}
我确信必须有更好的方法来做到这一点 - 最好是使用一个简单的正则表达式和一个简单的String.replaceAll()
。但是我无法想出来。
(之前我问partial version of this question,但我看不出如何调整完整案例的答案。这将教会我提出部分问题。)
答案 0 :(得分:1)
不要采用正则表达式的方式,因为那条路将永远变暗。考虑以下或其变型。根据合理的分隔符拆分字符串(可能是“前缀[”)并且要聪明地删除其余的大括号。
这是一个关闭袖带算法(StringUtils是org.apache.commons.lang.StringUtils):
StringUtils.splitByWholeSeparator()
似乎是一个很好的候选者(在此,返回值存储在blam中)。StringUtils.stripAll(blam)
StringUtils.strip(blam[0], ']');
。用这个字符串替换blam [0]。答案 1 :(得分:1)
这一个班轮:
String resultString = subjectString.replaceAll("(?<!prefix:(?:\\[\\w{0,2000000})?)[\\[\\]]", "");
当适用于:apple] [s [pears]前缀:[oranges] lemons] persimmons [pea [ches ap] ricots [] [[]]] []
会给你你想要的结果:
apples pears prefix:[oranges] lemons persimmons peaches apricots
您唯一的限制是前缀:[]之间的单词可以拥有的最大字符数。在这种情况下,限制是2000000.限制来自java,因为它不支持负面看后方的无限重复。
答案 2 :(得分:1)
有趣的问题。这是一个替代测试解决方案,不使用lookbehind。
public class TEST
{
public static void main( String[] args )
{
String orig = "apples [pears] prefix:[oranges] lemons ]persimmons[ pea[ches ap]ricots";
String result = debracketize(orig);
System.out.println(result);
}
private static String debracketize( String orig )
{
String re = // Don't indent to allow wide regex comments.
"(?x) # Set free-spacing mode. \n" +
"# Either capture (and put back via replace) stuff to be kept... \n" +
" ( # $1: Stuff to be kept. \n" +
" prefix:\\[[^\\[\\]]+\\] # Either the special sequence, \n" +
" | (?: # or... \n" +
" (?! # (Begin negative lookahead.) \n" +
" prefix: # If this is NOT the start \n" +
" \\[[^\\[\\]]+\\] # of the special sequence, \n" +
" ) # (End negative lookahead.) \n" +
" [^\\[\\]] # then match one non-bracket char. \n" +
" )+ # Do this one char at a time. \n" +
" ) # End $1: Stuff to be kept. \n" +
"| # Or... Don't capture stuff to be removed (un-special brackets)\n" +
" [\\[\\]]+ # One or more non-special brackets.";
return orig.replaceAll(re, "$1");
}
}
此方法使用两个全局替代方法。第一种方法是捕获(然后替换)特殊序列和非括号字符,第二种方法匹配(并删除)非特殊括号。
答案 3 :(得分:0)
如果你有一对你并不担心出现在原始字符中的字符(例如<>
),那么你可以先将你希望保留的方括号翻译成这些,去掉余数,然后改回翻译的括号。
这是ruby(移植到java希望不是太难,你只需要用捕获组进行全局搜索替换):
>> s = 'apple][s [pears] prefix:[oranges] lemons ]persimmons[ pea[ches ap]ricots [][[]]][]'
=> "apple][s [pears] prefix:[oranges] lemons ]persimmons[ pea[ches ap]ricots [][[]]][]"
>> s.gsub(/([^\[\]]+):\[([^\[\]]+)\]/, '\1:<\2>').gsub(/[\[\]]/,'').gsub(/</,'[').gsub(/>/,']')
=> "apples pears prefix:[oranges] lemons persimmons peaches apricots "
答案 4 :(得分:0)
1找出与prefix:\[[^\]]+\]
2使用相同的正则表达式来分割字符串
每个数组元素3,删除]或[(你的例子有两个元素)
4将元素与步骤1中的结果连接起来。
答案 5 :(得分:0)
这是你的正则表达式解决方案:
input.replaceAll("((?<!prefix:)\\[(?!oranges)|(?<!prefix:\\[oranges)\\])", "");
它使用两个负面外观来防止删除受保护前缀周围的方括号。如果您想保护多个字词,可以通过在正则表达式中将oranges
更改为(oranges|apples|pears)
来实现此目的。
以下是使用您的数据的测试:
public static void main(String... args) throws InterruptedException {
String input = "apple][s [pears] prefix:[oranges] lemons ]persimmons[ pea[ches ap]ricots [][[]]][]";
String result = input.replaceAll("((?<!prefix:)\\[(?!oranges)|(?<!prefix:\\[oranges)\\])", "");
System.out.println(result);
}
输出:
apples pears prefix:[oranges] lemons persimmons peaches apricots