9

为什么以下内容不会在 Android 中为我更改文本?

String content = "test\n=test=\ntest";
content = content.replaceAll("^=(.+)=$", "<size:large>$1</size:large>")

它返回原始值而不做任何更改。我希望它=test=<size:large>test</size:large>

我在这里想念什么?

编辑:好的,我明白为什么^并且$不工作。关键是我需要在一行的开头和结尾都匹配文本的东西,例如只包含“=一些文本=”的行。给出的大多数答案是不够的,原因如下:

=(.+)=与行尾没有任何关系,因此匹配任何包含两个=不并排的行。

.*=(.+)=.*匹配整行,但与上一个问题相同

\n=(.+)=\n越来越近,但不会匹配一行中的两行(例如test\n=test=\n=test=\ntest)它也不会匹配第一行或最后一行的实例

(?<=\n)=(.+)=(?=\n)几乎可以工作,但再次与第一行或最后一行的实例不匹配

(?<!.)=(.+)=(?!.)是唯一一个似乎实际上会匹配以 开头和结尾的每一行,=例如,但 $1 包含替换字符串和原始字符串。

content = content.replaceAll("(?<=(\n|^))=(.+)=(?=(\n|$))", "<size:large>$2</size:large>");是唯一似乎真正做它应该做的事情的答案。

4

5 回答 5

10

如果您打开多行模式,您的原始正则表达式可以正常工作,使用(?m)

content = content.replaceAll("(?m)^=(.+)=$", "<size:large>$1</size:large>");

现在确实在行边界处匹配^$

于 2012-08-24T00:37:30.490 回答
4

处理这个问题的最好方法是设置Pattern.MULTILINE. 使用MULTILINE,^$将匹配仅使用 , 分隔的行\n,并且将类似地处理输入的开头和输入的结尾。

使用String.replaceAll您需要使用嵌入式标志表达式在模式(?m)设置这些,例如MULTILINE

content = str.replaceAll("(?m)^=(.+)=$", "<size:large>$1</size:large>");

如果你使用MULTILINE,你需要对 使用积极的前瞻和后瞻\n,并且正则表达式会变得复杂以匹配第一行,如果最后没有\n,则匹配最后一行,例如如果我们的输入是:=test=\n=test=\n=test=\n=test=

String pattern = "(?<=(^|\n))=(.+)=(?=(\n|$))";
content = str.replaceAll(pattern, "<size:large>$2</size:large>");

在这种模式中,我们为后视提供选项:\n 输入的开头,(^|\n); 对于前瞻:\n 输入结束,(\n|$). 请注意,由于第一个or$2引入的组,我们需要在替换中用作捕获的组引用。

我们可以通过在非捕获组中的前瞻/后视中引入替代方案来使模式更加复杂,如下所示(?:)

String pattern = "(?<=(?:^|\n))=(.+)=(?=(?:\n|$))";
content = str.replaceAll(pattern, "<size:large>$1</size:large>");

现在我们回到$1在替换中使用作为捕获组。

于 2012-08-22T17:01:21.780 回答
3

在 Java 中,String 对象\n不被视为行首或行尾。这是一个换行符。为了匹配这一点,您需要将代码更改为

String content = "test\n=test=\ntest";
content = content.replaceAll("\n=(.+)=\n", "\n<size:large>$1</size:large>\n");

什么^$匹配,是字符串对象本身的开始和结束。

如果您正在从文件中读取,则换行符可能是 CRLF 字符,在这种情况下您也想匹配\r。在这种情况下,您需要使用这样的正则表达式

content = content.replaceAll("[\n\r]=(.+)=[\n\r]", "\n<size:large>$1</size:large>\n");

如果您需要匹配以在同一字符串中的多个“行”中的多个实例中工作,则应首先将字符串拆分为多行。

String content = "test\n=test=\n=test=\ntest";
String[] pieces = content.split("[\r\n]");
StringBuilder replaced = new StringBuilder();

for (int i=0; i<pieces.length; i++) {
    String piece = pieces[i].replaceAll("^=(.+)=$", "<size:large>$1</size:large>");
    replaced.append(piece);
    replaced.append('\n');
}
于 2012-08-22T16:36:53.267 回答
0

好吧,正如您已经说过的,这是正则表达式的开始/结束标记的问题。^不是一行的开头,而是整个字符串的开头,同样$是整个字符串的结尾。

尝试更改表达式:^.*=(.+)=.*$或忽略这些标记:=(.+)=

要匹配行的开头,您可以使用:(?:^|\n)=(.*)=. 从我在纯 Java 中的测试来看,似乎无法识别尾随换行符,但在 Android 中可能会有所不同。

于 2012-08-22T16:33:40.433 回答
0

好的,我想我有一个答案......这似乎有效:

content = content.replaceAll("(?<!.)=(.+)=(?!.)", "<size:large>$1</size:large>")

不是吗?

编辑:以上不起作用,由于某种原因,它复制了原始文本并将其放在替换文本之后......这是最终起作用的:

content = content.replaceAll("(?<=(\n|^))=(.+)=(?=(\n|$))", "<size:large>$2</size:large>");
于 2012-08-22T16:53:46.587 回答