sed: 行頭の 4 つのスペースを 2 つのスペースに置き換えます。

sed: 行頭の 4 つのスペースを 2 つのスペースに置き換えます。

たとえば、インデントが 4 つのスペースである次の (puppet) ファイルがあるとします (処理する必要があるファイルがたくさんあります)。

# 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 スペースの発生が置き換えられるだけでなく、より深いインデントが含まれなくなります。

行頭の 4 つのスペースをそれぞれ 2 つのスペースに置き換えることができる正規表現はありますか? 単純な正規表現と 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 には変更されたコードが出力されます。

関連情報