Регулярное выражение для изменения количества пробелов на уровне отступа
Скажем, у вас есть строки, похожие на это
1 int some_function() {
2 int x = 3; // Some silly comment
И так далее. Отступ делается с пробелами, и каждый отступ имеет два пробела.
Вы хотите изменить каждый отступ на три пробела. Простое регулярное выражение
s/ {2}/ /g
Не работает для вас, потому что это изменяет некоторые недопустимые пробелы; в этом случае он меняет два пробела перед // Some silly comment
на три пробела, что нежелательно. (Это становится намного хуже, если есть таблицы или комментарии, выровненные на заднем конце строки.)
Вы не можете просто использовать
/^( {2})+/
Потому что что бы вы его заменили? Я не знаю простого способа узнать, сколько раз +
было сопоставлено в регулярном выражении, поэтому мы не знаем, сколько измененных отступов нужно вставить.
Вы всегда можете идти по очереди и отрезать отступы, измерять их, строить новую строку отступа и привязывать ее к строке, но было бы намного проще, если бы существовало регулярное выражение.
Существует ли регулярное выражение для замены уровней отступа, как описано выше?
Ответы
Ответ 1
В некоторых вариантах регулярных выражений вы можете использовать lookbehind:
s/(?<=^ *) / /g
Во всех других вариантах вы можете изменить строку, использовать lookahead (который поддерживает все варианты) и наоборот:
s/ (?= *$)/ /g
Ответ 2
Здесь другой, вместо использования \G
, который имеет NET, PCRE (C, PHP, R...), Java, Perl и Ruby поддержка:
s/(^|\G) {2}/ /g
\G
[...] может совпадать на одной из двух позиций:
✽ Начало строки,
✽ Позиция, которая немедленно следует за окончанием предыдущего совпадения.
Источник: http://www.rexegg.com/regex-anchors.html#G
Мы используем его способность сопоставляться в позиции, которая сразу же следует за концом предыдущего совпадения, который в этом случае будет в начале строки, за которым следуют 2 пробела (ИЛИ предыдущее совпадение в соответствии с вышеупомянутым правилом).
См. пример: https://regex101.com/r/qY6dS0/1
Ответ 3
Мне нужно было вдвое уменьшить количество пробелов на отступе. То есть, если отступ был 4 пробела, мне нужно было изменить его на 2 пробела. Я не мог придумать регулярное выражение. Но, к счастью, кто-то еще сделал:
//search for
^( +)\1
//replace with (or \1, in some programs, like geany)
$1
Из источника: " ^( +)\1
означает" любую последовательность пробелов ненулевой длины в начале строки, за которой следует та же последовательность пробелов. \1
в шаблоне и $1
в замене являются обратными ссылками на начальную последовательность пробелов. Результат: вдвое вдвое.
Ответ 4
Вы можете попробовать следующее:
^(\s{2})|((?<=\n(\s)+))(\s{2})
Структура:
^(\s{2}) = Searches for two spaces at the beginning of the line
((?<=\n(\s)+))(\s{2}) = Searches for two spaces
but only if a new line followed by any number of spaces is in front of it.
(This prevents two spaces within the line being replaced)
Я не совсем знаком с perl, но я бы попробовал это, чтобы увидеть, работает ли он:
s/^(\s{2})|((?<=\n(\s)+))(\s{2})/\s\s\s/g
Как отметил @Jan, могут быть и другие непространственные пробельные символы. Если это проблема, попробуйте следующее:
s/^( {2})|((?<=\n( )+))( {2})/ /g