Подтвердить что ты не робот

Регулярное выражение для изменения количества пробелов на уровне отступа

Скажем, у вас есть строки, похожие на это

1  int some_function() {
2    int x = 3;  // Some silly comment

И так далее. Отступ делается с пробелами, и каждый отступ имеет два пробела.

Вы хотите изменить каждый отступ на три пробела. Простое регулярное выражение

s/ {2}/   /g

Не работает для вас, потому что это изменяет некоторые недопустимые пробелы; в этом случае он меняет два пробела перед // Some silly comment на три пробела, что нежелательно. (Это становится намного хуже, если есть таблицы или комментарии, выровненные на заднем конце строки.)

Вы не можете просто использовать

/^( {2})+/

Потому что что бы вы его заменили? Я не знаю простого способа узнать, сколько раз + было сопоставлено в регулярном выражении, поэтому мы не знаем, сколько измененных отступов нужно вставить.

Вы всегда можете идти по очереди и отрезать отступы, измерять их, строить новую строку отступа и привязывать ее к строке, но было бы намного проще, если бы существовало регулярное выражение.

Существует ли регулярное выражение для замены уровней отступа, как описано выше?

4b9b3361

Ответ 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