Допустим, у меня есть этот файл (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 будет содержать ваш измененный код.