sed: заменить каждое появление 4 пробелов (в начале строки) на 2 пробела

sed: заменить каждое появление 4 пробелов (в начале строки) на 2 пробела

Допустим, у меня есть этот файл (puppet) с отступом в 4 пробела (у меня их много, и мне нужно их обработать):

# init.pp
class hardwareid (
    $package_name      = $hardwareid::params::package_name,
    $package_category  = $hardwareid::params::package_category,
    $package_ensure    = $hardwareid::params::package_ensure

) inherits hardwareid::params {

    package { "${package_name}":
        name      => $package_name,
        category  => $package_category,
        ensure    => $package_ensure,
    }
}

Я хочу использовать sed для замены каждого вхождения 4 пробелов в начале строки на 2 пробела, чтобы получить такой результат:

class hardwareid (
  $package_name      = $hardwareid::params::package_name,
  $package_category  = $hardwareid::params::package_category,
  $package_ensure    = $hardwareid::params::package_ensure

) inherits hardwareid::params {

  package { "${package_name}":
    name      => $package_name,
    category  => $package_category,
    ensure    => $package_ensure,
  }
}

Все, что я пока придумал, это:

sed -i -e 's/^\s\{4\}/  /g' init.pp

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

Есть ли регулярное выражение, которое может заменить каждый 4xspace в начале строки на 2xspace? Возможно ли это вообще с простыми регулярными выражениями и sed, или мне придется переключиться на awk/perl/python/ruby, так как мне придется подсчитывать вхождения, чтобы заменить их на то же число?

РЕДАКТИРОВАТЬ

Этот вопрос глупый (хотя в простом случае все работает). Но я не должен форматировать свой код без инструмента, который понимает язык моего кода (это Puppet). Даже если у меня есть идеальное регулярное выражение (например, предоставленное внутри ответов), у меня есть проблема: если я случайно применю регулярное выражение больше 1 раза, отступы снова будут нарушены. Ребята из Puppet работают над этой проблемой:http://projects.puppetlabs.com/issues/8031Пока это не решено, мне нужно быть осторожным при конвертации файлов. Или написать настоящий форматтер самому (что не должно быть так уж сложно).

решение1

perl -pe 's{^((?:    )+)}{substr($&, length($&)/2)}e'

решение2

Вы, возможно, пытаетесь использовать не тот инструмент. Возможно, вы могли бы прийти к решению sed, но есть инструмент, созданный для этого, который будет работать гораздо быстрее.

http://perltidy.sourceforge.net/

Взгляните на perltidy. Это модуль perl, который доступен в большинстве дистрибутивов.

Если он установлен правильно, его можно вызвать, набрав 'perltidy'. Чтобы добиться того, что вы ищете, следующее должно сработать.

perltidy -i=2 <filename> 

Это должно создать новый файл с изменениями с расширением .tdy. Хотя perltidy изначально был написан для perl, он может работать и работает хорошо на многих других языках кода. Его можно легко вызывать в популярных редакторах и использовать вместе с общим .tidyrc, который можно использовать для поддержания/обеспечения стандарта кодирования. Доступны обширные опции, которые позволят вам контролировать каждый аспект его обработки кода.

решение3

Поскольку ответ perltidy не сработал в вашем коде, используйте этот.

perl -pe 's{^(\s*)}{" " x (length($1)/2)}e'

Передайте имя файла в конце строки или передайте файл в STDIN. STDOUT будет содержать ваш измененный код.

Связанный контент