#java #regex #string
#java #регулярное выражение #строка
Вопрос:
Это вопрос «что, черт возьми, здесь происходит». На самом деле мне не нужно решение.
Мне пришлось заменить все одиночные обратные косые черты в строке двойными обратными косыми чертами . Это то, что я в итоге сделал…
strRootDirectory = strRootDirectory.replaceAll("\\", "\\\\");
…где strRootDirectory — это java.lang .Строка выше.
Теперь я понимаю четыре обратных косых черты для первого аргумента: регулярное выражение ожидает две обратные косые черты, чтобы указать одну буквальную обратную косую черту, и java хочет, чтобы они удвоились. Это нормально.
НО, что, черт возьми, происходит с восемью обратными косыми чертами для второго аргумента? Разве строка замены не должна быть буквальной (я имею в виду, нерегулярной) строкой? Я ожидал, что мне понадобится четыре обратных косых черты во втором аргументе, чтобы представить две обратные косые черты.
Комментарии:
1. Да, Java обратная косая черта. Попробуйте Python:
re.sub(r"\", r"\\", mystr)
2. Или просто используйте соответствующий инструмент для работы — не используйте регулярные выражения, когда они вам не нужны…
3. Или используйте соответствующую операционную систему для работы — не используйте Windows, если она вам не нужна. Обратите внимание, что Java поддерживает прямые косые черты там, где Windows обычно хотела бы использовать обратную косую черту.
4. Может быть, я переключусь на ручку, бумагу и счеты.
Ответ №1:
Второй аргумент — это не строка регулярного выражения, а строка замены регулярного выражения, в которой обратная косая черта также имеет особое значение (она используется для экранирования специального символа $
, используемого для интерполяции переменных, а также используется для экранирования самого себя).
Из API:
Обратите внимание, что обратная косая черта (
) и знаки доллара (
$
) в строке замены могут привести к тому, что результаты будут отличаться от того, если бы они обрабатывались как строка буквальной замены; см.Matcher.replaceAll
.Matcher.quoteReplacement(java.lang.String)
При желании используйте для подавления специального значения этих символов.— http://download.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll (…)
Комментарии:
1. ОИК! Я думал, что аргумент два — это дословная строка (т. Е. Без специальных символов), которая должна быть записана вместо строки регулярного выражения аргумента. Спасибо!
2. Нет проблем, Джон. То же самое сбило меня с толку, когда я впервые столкнулся с этим! 🙂
3. @JohnFitzpatrick
String.replace()
функция принимает 2 дословные строки (без регулярных выражений или специальных символов) см. Мой ответ4. @ratchet freak, да,
replace(...)
здесь лучший вариант.5. @ratchet: Спасибо, что подтвердили мое здравомыслие. Я был уверен, что в какой-то форме замены строки второй аргумент был буквальным.
Ответ №2:
Это проще, если вы используете replace("\","\\")
( String.replace
принимает литеральные строки и более эффективен, когда все это литерально)
или вы можете обеспечить корректность с помощью функций Pattern.quote
и Matcher.quoteReplacement
Комментарии:
1. Спасибо за предложение. С помощью replace() Мне пришлось бы выполнять цикл до завершения, потому что исходная строка содержит много обратных косых черт, а затем на второй итерации я подозреваю, что первой найденной обратной косой чертой будет та, которую я только что поместил туда из последнего replace() . Я думаю, что бесконечный цикл, если replace() не может отслеживать, что он в последний раз заменял.
2. нет, он «заменяет каждую подстроку этой строки, которая соответствует буквенной целевой последовательности, указанной буквенной последовательностью замены». проверьте ссылку в ответе
Ответ №3:
"\\\\"
приводит к представлению в памяти строки с 4 обратными косыми чертами : \\
. Хотя вторая строка не является строкой регулярного выражения, обратная косая черта и знаки доллара по-прежнему являются специальными символами в ней, поэтому их нужно экранировать.
Комментарии:
1. Но замена не является строкой регулярного выражения: другие метасимволы регулярных выражений не нужно экранировать.
2. Это тоже не обычная строка. Смотрите
Bart
размещенную ссылку.3. Я знаю, это тот же Барт . 🙂
4. @BartKiers: Ах, извините. Я не смотрел на ваше имя при чтении вашего комментария, я думал, что ОП написал это 🙂
Ответ №4:
Согласно справочным материалам Java, метод replaceAll интерпретирует обратные косые черты в строке замены также как escape-символы. Они могут использоваться для экранирования символа знака доллара, который может ссылаться на совпадающие выражения для повторного использования в строке замены. поэтому, естественно, если вы хотите удвоить количество обратных косых черт, и оба параметра обрабатывают обратную косую черту как escape-символ, вам нужно в два раза больше обратных косых черт в строке замены.
Ответ №5:
Да, это становится сложным, когда вам нужно делать такие вещи, не так ли.
Причина, по которой вам нужно так много обратных косых черт, заключается в том, что вам нужно учитывать, что обратная косая черта используется как для экранирования строки, так и для экранирования регулярного выражения.
- Возьмите 1 обратную косую черту.
- Удвойте его для экранирования строки.
- Удвойте его снова для экранирования регулярных выражений.
- Удвойте его еще раз, потому что вам нужно сопоставить две последовательные обратные косые черты в исходной строке.
Это составляет 8.
Ответ №6:
Как любитель не вдаваться в сверхдетальные объяснения регулярных выражений… Я понял из основного ответа Барта Кирса выше:
System.out.println( "line1: " "hello\\world" );
System.out.println( "line2: " "hello\\world".replaceAll("\\\\", Matcher.quoteReplacement("\") ) );
выводит
line1: hello\world
line2: helloworld
Надеюсь, это поможет…