Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Say I have this (puppet) file with an indentation of 4 spaces (I have a bunch of them that I have to process):

# 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,
    }
}

I want to use sed to replace each occurence of 4 spaces at the beginning of a line with 2 spaces, to get this result:

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,
  }
}

All I came up so far ist this:

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

but this will not only replace occurences of 1x4 Spaces and therefore not include deeper indentations.

Is there a regex which can replace each 4xspace at beginning of a line with 2xspace? Is that even possible with simple regexes and sed, or do I have to switch to awk/perl/python/ruby, since I have to count the occurences to replace them with the same number?

EDIT

This question is stupid (although for a simple case, it all works). But I should not format my code without a tool that does understand the language of my code (which is Puppet). Even if I have the perfect regex (like provided inside the answers), I have the problem that if I accidentally apply the regex more than 1 time, the indentation is broken again. The Puppet guys are working on that issue: http://projects.puppetlabs.com/issues/8031 until it is solved, I have to be careful when converting files. Or write a real formatter myself (which should not be that hard).

share|improve this question
    
With the "/g" at the end, it should "globally" replace the pattern within the line. So I would think that it should cover multiples of the 4 space indentation. –  pottsdl May 8 '12 at 14:39
    
@pottsdl Not with the ^ (start of line)... –  Bob May 8 '12 at 14:40
    
Thanks @Bob, I missed that the first time. –  pottsdl May 8 '12 at 14:45

3 Answers 3

up vote 3 down vote accepted
perl -pe 's{^((?:    )+)}{substr($&, length($&)/2)}e'
share|improve this answer

You might be trying to use the wrong tool. It is possible that you could arrive at a sed solution but there is a tool built for this that will work much more quickly.

http://perltidy.sourceforge.net/

Take a look at perltidy. It is a perl module that is available in most distributions.

If it is installed correctly it can be invoked by typing 'perltidy'. To achieve what you are looking for the following should work.

perltidy -i=2 <filename> 

This should create a new file with the changes with a .tdy extension. While perltidy was written initially for perl, it can and does work well on many other languages of code. It can be easily invoked within popular editors and used in conjunction with a common .tidyrc can be used to maintain/enforce a coding standard. There are extensive options available that will let you control every aspect of its treatment of the code.

share|improve this answer
    
perltidy seems to be suited only towards Perl scripts: "Perltidy is a Perl script which indents and reformats Perl scripts to make them easier to read". When invoked on my example, it complains about Syntax errors. –  ifischer May 8 '12 at 15:02
    
I have used it effectively on C and Java, though that said those are all somewhat C based and share similar syntax. It is possible that tweaking some of the options might resolve the error, but it may not be possible. –  AaronM May 8 '12 at 15:19

As the perltidy answer did not work on your code use this.

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

Pass the name of the file at the end of the line or pipe the file into STDIN. STDOUT will be your modified code.

share|improve this answer
    
heh see someone else provided the same while I was testing it. –  AaronM May 8 '12 at 15:21

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.