Scala:将字符串变量作为字符串而不是正则表达式处理

3
能否无缝完成这个任务?
 scala> val p = "$"
 scala> "hello, I have 65 dollars".replaceFirst("dollars", p)

当前结果为

 java.lang.StringIndexOutOfBoundsException: String index out of range: 1
 ....

在scala 2.10中的预期结果:

 hello, I have 65 $

问题出在变量p中存储的符号$,我需要将其作为字符串而不是正则表达式进行处理。
注意:我不能修改(例如替换所有非字母符号)p变量(只能使用标准函数,例如.toString)。
注意2:给定的示例是一个玩具示例。我希望有一个更通用的解决方案。即变量p可以包含任何类型的内容(符号、数字、文本等),因此用“\\$”替换“$”并没有太多意义。
(这是类似问题的改进版本:scala string, raw string

相关内容:https://dev59.com/ZmfWa4cB1Zd3GeqPjKq8 - om-nom-nom
@om-nom-nom 是的,我已经读过了,但是有一个替代方法...难道没有一种方法可以在不猜测变量p可能包含什么内容的情况下完成任务,以避免出错吗? - xhudik
@Jesper 这是一个非常不同的问题,请查看注释2。 - xhudik
3个回答

2

还有其他方法来做吗?如果没有,我需要用什么符号替换?我知道 $ 和 \ -还有其他的吗?变量p可以包含任何内容(文本、符号、数字等),因此我需要摆脱所有的“特殊字符”。 - xhudik
哦,我误解了你的问题。我以为你只是关心美元符号。我更新了我的答案。 - Hanno
我想放一个简单的例子 - 可能我会编辑它。无论如何感谢你的回答。 - xhudik
引用是一个有趣的观点,但我会等待看看是否会出现其他东西。 - xhudik
我尝试了你的建议,但它不起作用:"i have 65 dollars".replaceFirst("dollars", Pattern.quote("$"))。会出现非法组引用错误。 - xhudik

2

使用 Regex.quote 处理模式字符串,使用 quoteReplacement 处理替换字符串。(这些方法底层实际调用了 Pattern。)

scala> import util.matching._
import util.matching._

scala> "hello, I have 65 dollars".replaceFirst("dollars", Regex quoteReplacement p)
res7: String = hello, I have 65 $

scala> "dollars".r replaceFirstIn ("hello, I have 65 dollars", Regex quoteReplacement p)
res8: String = hello, I have 65 $

scala> "hello, I have 65 dollars".replaceAllLiterally("dollars", p) // quotes both
res9: String = hello, I have 65 $

1
问题在于replaceFirst()使用正则表达式,因此:
"65 dollars".replaceFirst("dollars","$0") // compiles
"65 dollars".replaceFirst("dollars","$")  // throws "StringIndexOutOfBoundsException"

如果,
val dollars = "$"

您可以转义$符号,

"65 dollars".replaceFirst( "dollars", if(dollars == "$") "\\$" else dollars )

或者使用字符串插值。
s"65 $dollars"

或者采用老式的字符串操作方法,
val t = "65 dollars".split("dollars"); if(t.size>1) t.mkString(dollars) else t(0) + dollars

或者使用地图,
val ff = "dollars"
val r1 = "$"
"65 dollars, 3 dollars, 50 dollars".split(ff).zipWithIndex.map{case (t,0) => t+r1; case (t,_) => t+ff}.mkString

请看我的注释2,我正在寻找一些通用的解决方案,而不仅仅是针对$。这意味着我不愿意替换所有可能的转义和特殊字符($,\,&,@,以及其他可能的),而是将变量p视为字符串而不是正则表达式。 - xhudik
这就是为什么我提供了多种解决方案。你可以尝试使用字符串插值。我点赞了你的问题,因为$符号可能会在正则表达式中导致意外错误。 - Keith Pinson
谢谢Keith,但这仍然不是预期的答案。例如,如果您的变量dollars包含“\”,它将抛出错误。是的,您解决了$问题,但其他符号(例如“\”)可能会出现类似的问题。正如您所述,replaceFirst将其参数作为正则表达式-是否可以将此“特性”更改为接受字符串而不是正则表达式?或者,使用其他可以完成工作的“replaceFirst”函数? - xhudik
我不知道有一个函数可以解析字符串以便将其用于正则表达式的字符串替换中进行清理。如果你不使用正则表达式,你仍然需要处理孤立的反斜杠"",就像你发现的那样。顺便说一下,replace()方法并不使用正则表达式,虽然replaceFirst()方法使用。 - Keith Pinson
是的,replace和replaceAllLitarally按照需要工作。唯一的问题是它们替换所有出现的内容而不是我需要的第一个。谢谢Keith! - xhudik
在我的回答中添加了一个示例,用一个映射替换了找到的第一个字符串 :) - Keith Pinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接