sed を使用して先頭のタブを 4 つのスペースに置き換えるにはどうすればよいでしょうか?

sed を使用して先頭のタブを 4 つのスペースに置き換えるにはどうすればよいでしょうか?

vim では次のように実行できるようです:

:s/^\t\+/\=repeat('    ',len(submatch(0)))

これが sed にどのように変換されるかわかりませんでした。次のことを試しました:

sed -ri "s/^\t\+/\=repeat('    ',len(submatch(0)))/g" test.txt

コマンドは効果がないようです。

答え1

これはexpand、例えば のためですexpand -t 4 file.txt

expand元のファイルは編集されませんが、新しいファイルにリダイレクトしてmv元のファイルを上書きしたり、spongeインストールされている場合は使用したりできます。例:

    expand -t 4 file.txt > file.new && mv file.new file.txt
or 
    expand -t 4 file.txt | sponge file.txt

参考までに、unexpand逆の操作、つまり複数のスペースをタブに変換する方法を参照してください。

expandとはどちらもunexpand固定幅タブの使用をサポートしています (例:-t 4または-t 8など)またはタブ位置のリスト (例-t 4,12,32)。先頭のスペース/タブのみを変換するオプションもあります。詳細については、man ページを参照してください。


の詳細についてはspongeman spongeおよびを参照してください。ファイルをそれ自身にパイプするための、sponge の標準的な代替手段はありますか?つまり、一時ファイルを使用してリダイレクトと mv を実行します。ちなみに、stdout を現在 stdin として使用されている同じファイルにリダイレクトしないでください。シェルは、読み取られる前にそれを上書きします。

spongeもっと見るパッケージ。


追記:こちらもご覧くださいGNUインデントまたは、他の多くの同様のソースコード再フォーマット ツールのいずれか。

答え2

$ cat -T /tmp/test.txt
^I^I^I3^I<= this final tab should remain
^I^I2
^I1

sed の使用:

sed ':loop;s/^\( *\)\t/\1    /;tloop' /tmp/test.txt | cat -T
            3^I<= this final tab should remain
        2
    1

loop上記は、先頭のスペースと先頭のタブを捕捉し、スペースを置き換えてタブを 4 つのスペースに変換するループ(皮肉なことに というラベルが付けられている) を設定し、成功した場合 ( t)、ループに戻ります。https://stackoverflow.com/a/35017207/493161

関連情報