Регулярное выражение для соответствия только неэпизованным специальным символам
Я пытаюсь найти регулярное выражение, которое может соответствовать только символам, которым не предшествует специальная escape-последовательность в строке.
Например, в строке Is ? stranded//?
я хочу иметь возможность заменить ?
, который не был экранирован с другой строкой, поэтому я могу получить этот результат: **Is Dave stranded?**
Но для жизни я не смог найти способ. Я только придумал регулярные выражения, которые едят все сменные символы.
Как вы создаете регулярное выражение, которое соответствует только символам, которым не предшествует escape-последовательность?
Ответы
Ответ 1
Попробуйте этот код Java:
str="Is ? stranded//?";
Pattern p = Pattern.compile("(?<!//)([?])");
m = p.matcher(str);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, m.group(1).replace("?", "Dave"));
}
m.appendTail(sb);
String s = sb.toString().replace("//", "");
System.out.println("Output: " + s);
OUTPUT
Output: Is Dave stranded?
Ответ 2
Используйте отрицательный lookbehind, это то, что они предназначены для создания!
(<?!//) [? \]
Чтобы остановить его:
(
?<! #The negative look behind. It will check that the following slashes do not exist.
// #The slashes you are trying to avoid.
)
[\?] #Your special charactor list.
Только если//не может быть найден, он будет работать с остальной частью поиска.
Я думаю, что в Java ему нужно будет снова экранировать как строку, например:
Pattern p = Pattern.compile("(?<!//)[\\?]");
Ответ 3
Используйте группировку. Вот один пример:
import java.util.regex.*;
class Test {
public static void main(String[] args) {
Pattern p = Pattern.compile("([^/][^/])(\\?)");
String s = "Is ? stranded//?";
Matcher m = p.matcher(s);
if (m.matches)
s = m.replaceAll("$1XXX").replace("//", "");
System.out.println(s + " -> " + s);
}
}
Вывод:
$ java Test
Is ? stranded//? -> Is XXX stranded?
В этом примере я:
- первая замена любого неэкспериментированного? с "XXX",
- затем удалив escape-последовательности "//".
EDIT Используйте if (m.matches)
, чтобы убедиться, что вы неправильно обрабатываете строки, не соответствующие друг другу.
Это просто быстрый и грязный пример. Очевидно, вам нужно сделать это, чтобы сделать его более надежным. Но он получает общую идею.
Ответ 4
Я думал об этом и имел второе более простое решение, избегая регулярных выражений. Другие ответы, вероятно, лучше, но я думал, что могу опубликовать его в любом случае.
String input = "Is ? stranded//?";
String output = input
.replace("//?", "a717efbc-84a9-46bf-b1be-8a9fb714fce8")
.replace("?", "Dave")
.replace("a717efbc-84a9-46bf-b1be-8a9fb714fce8", "?");
Просто защитите "//?" заменив его чем-то уникальным (например, guid). Тогда вы знаете, что любые оставшиеся вопросительные знаки являются честной игрой.
Ответ 5
Совпадение по набору символов, отличных от escape-последовательности, затем специальный символ регулярного выражения. Вы можете использовать инвертированный класс символов ([^/]
) для первого бита. Особым случаем является неэкранированный символ регулярного выражения в начале строки.
Ответ 6
попробуйте сопоставить:
(^|(^.)|(.[^/])|([^/].))[special characters list]
Ответ 7
String aString = "Is ? stranded//?";
String regex = "(?<!//)[^a-z^A-Z^\\s^/]";
System.out.println(aString.replaceAll(regex, "Dave"));
Часть регулярного выражения [^a-z^A-Z^\\s^/]
соответствует не-буквенно-цифровым символам, пробелам или непересылаемым символам косой черты.
Часть (?<!//)
делает отрицательный lookbehind - см. docco здесь для получения дополнительной информации
Это дает выход Is Dave stranded//?
Ответ 8
Я использовал этот:
((?:^|[^\\])(?:\\\\)*[ESCAPABLE CHARACTERS HERE])
Демо: https://regex101.com/r/zH1zO3/4