2013-04-09 2 views
3

Легко ли это сделать?scala, строковая переменная, обработанная как строка не regexp

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, которая хранит символ $, мне нужно обработать его в виде строки не регулярное выражение.

Примечание:Я не могу изменить (например, заменить все небуквенные символов) р переменной (только стандартные функции, например, .ToString)

Примечание2: Данный пример является скорее игрушкой -пример. Я был бы признателен за более общее решение. То есть переменная p может содержать любой тип содержимого (символы, цифры, текст, ...), поэтому замена «$» на «\\ $» doesn.t имеет смысл

(это улучшенная версия аналогичной проблемы: scala string, raw string)

+0

Связанные http://stackoverflow.com/questions/12115187/replace-with –

+0

@ ом-ном-ном да, я прочитал это уже, но есть замена .. . Не существует какой-либо метод, который бы выполнял задачу, не догадываясь, какая переменная p может или не может содержать, чтобы не получить ошибку? – xhudik

+0

@Jesper это различный другой вопрос см. Примечание2 – 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 $ 
+0

не очень интуитивно понятен, но работает - спасибо! – xhudik

2

Вам необходимо избегать символа доллара, потому что Java uses it in its implementation of regular expressions as a group reference.

Вы отметили, что вы не можете изменить строковый литерал в переменной р, так что вам нужно прибегать к замене знака доллара и другие специальные символы, такие как this:

Pattern.quote(p); 
+0

нет ли какой-либо другой метод, как это сделать?Если нет, какие символы мне нужно заменить? Я знаю, что $ и \ -что еще? Переменная p может содержать все (текст, символы, цифры, ..), поэтому мне нужно избавиться от всех «специальных символов» – xhudik

+0

О, я понял ваш вопрос неправильно. Я думал, вы просто обеспокоены символом доллара. Обновлен мой ответ. – Hanno

+0

Я хотел привести простой пример - возможно, я его отредактирую. Спасибо за ответ в любом случае – xhudik

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

PLS см. мою заметку2, я ищу какое-то общее решение, а не только для $. Это означает, что я не хочу заменять все возможные escape и специальные символы ($, \, &, @, и кто знает, что еще), но обрабатывать переменную p как строку вместо regexp – xhudik

+0

Вот почему я предоставил несколько решений. Вы можете попробовать строку интерполяции. Я рассмотрел ваш вопрос, потому что символ $ может быть неожиданной ошибкой «getcha» в regex. –

+0

благодарит Кейта, но все же это не ожидаемый ответ. например если ваши переменные доллары содержат «\», это вызовет ошибку. Да, вы решили проблему $, но могут быть подобные проблемы с другими символами, например. "\". Как вы уже сказали, replaceFirst принимает свою рекомендацию как regexp - возможно ли изменить эту «функцию» на принимающую строку вместо regexp. Или используйте другую функцию «replaceFirst», которая будет выполнять эту работу? – xhudik

Смежные вопросы