2013-04-09 46 views
3

它可以无缝地执行吗?scala,作为字符串处理的字符串变量不是正则表达式

scala> val p = "$" 
scala> "hello, I have 65 dollars".replaceFirst("dollars", p) 

当前结果是

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

预期的结果在阶2.10:

hello, I have 65 $ 

问题是与可变p存储符号$,我需要处理它作为一个字符串不正则表达式。

注:我不能修改(例如更换所有非字母符号)的变量p(仅标准功能,例如的ToString)

注2:该给定的例子是相当玩具-例。我会欣赏更通用的解决方案。即可变p可以包含任何类型的内容(符号,数字,文字,...),因此替换“$”为“\\ $” doesn.t多大意义

(这是改善类似问题的版本: scala string, raw string

+0

相关http://stackoverflow.com/questions/12115187/replace-with – 2013-04-09 10:13:20

+0

@ OM-NOM-NOM是的,我读它了,但有更换.. 。不存在某种方法可以在不猜测变量p可以包含或不能包含的情况下执行任务,以避免出错? – xhudik 2013-04-09 10:17:14

+0

@Jesper这是不同的问题见note2 – xhudik 2013-04-09 13:15:11

回答

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 $ 
+0

不是非常直观,但它工作正常 - 谢谢! – xhudik 2014-04-28 08:37:41

2

您需要转义美元符号字面值,因为Java uses it in its implementation of regular expressions as a group reference

您注意的是,你不能修改字符串中的p变量文字,所以你需要求助于取代美元符号和其他特殊字符,如this

Pattern.quote(p); 
+0

是不是还有其他一些方法怎么做呢?如果不是,我需要替换哪些符号?我知道$和\ - 别的吗?变量p可以包含所有东西(文本,符号,数字,..)因此我需要摆脱所有“特殊字符” – xhudik 2013-04-09 10:23:06

+0

哦,我理解你的问题是错误的。我以为你只关心美元符号。更新了我的答案。 – Hanno 2013-04-09 10:28:02

+0

我想举个简单的例子 - 可能我会编辑它。无论如何感谢您的回答 – xhudik 2013-04-09 10:30:05

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 
+0

请参阅我的note2,我正在寻找一些通用的解决方案,而不仅仅是$。这意味着我不愿意替换所有可能的转义字符和特殊字符($,\,&,@,以及谁知道还有什么),而是像字符串那样对待变量p,而不是正则表达式 – xhudik 2013-04-09 13:20:58

+0

这就是我提供多种解决方案的原因。你可能会尝试字符串插值。我提高了你的问题,因为$符号可能是正则表达式中的“gotcha”意外错误。 – 2013-04-09 13:27:46

+0

感谢Keith,但仍然不是预期的答案。例如如果您的变量美元包含“\”,则会引发错误。是的,您解决了$问题,但其他符号可能存在​​类似问题,例如“\”。正如你所说replaceFirst把它作为正则表达式 - 是否有可能将这个“功能”改为接受字符串,而不是正则表达式。或者,使用其他可以完成这项工作的“replaceFirst”函数? – xhudik 2013-04-10 11:10:44