先行タブ文字(一部の空白文字の後のタブ文字を含む)のみを置き換える方法は?

先行タブ文字(一部の空白文字の後のタブ文字を含む)のみを置き換える方法は?

タブ、スペース、またはその両方にインデントされたいくつかのファイルがあります。先行タブを空白に変換したい(タブ1つを空白4つに)。これには、いくつかの先行スペースの後ろのタブが含まれます。以下は、入力ラインと期待される結果のいくつかの例です。

+----+---+---+
|番号|元の行|予想結果|
+----+---+---+
1 | ␣␣␣␣␣xxx |
2 | ␣␣␣␣␣␣␣xxx |
3 | \t␣\txxx ␣␣␣␣␣␣␣␣␣xxx |
4 | ␣␣␣␣x\txx |
+----+---+---+

expandスペースとタブの混合を処理できないため、ここではコマンドを使用できません。以下は例です。

user1@ubuntu$ printf "\t  \txxx" | od -t a
0000000  ht  sp  sp  ht   x   x   x
0000007
user1@ubuntu$ printf "\t  \txxx" | expand -i -t 4 | od -t a
0000000  sp  sp  sp  sp  sp  sp  sp  sp   x   x   x
0000013
user1@ubuntu$ 

ご覧のとおり、元の文字列の2つのスペースは単に削除されました。私の問題を解決する方法?このサイトで他の同様の質問を読みましたが、私の質問とまったく同じではありません。

答え1

cat -Tsedを使用できます(タブが表示されたときにファイルを表示するために使用されます^I)。

$ cat -T file
^I abc
^I  ^Ixde^Inot
$ sed ':x;s|^\( *\)\t|\1    |;tx' file | cat -T
     abc
          xde^Inot

残念ながら、asタブの解釈は\tPOSIX仕様ではなくGNU sed拡張です。ただし、この問題を解決できますprintfGillesが説明したように使用してください。書き込み:

sed ":x;s|^\( *\)$(printf '\t')|\1    |;tx" file

sedはそこで何をしていますか?

  • s|^\( *\)\t|\1 |

sedが行の先頭に固定されている0個以上の空白文字が続くタブ文字を見つけると、タブ文字を4つの空白に置き換えます。ペアは、\(\)ゼロ個以上の前の空白文字で構成される一致グループの発生に分けられます\1

  • tx

交換した場合はラベルに移動します:x。それ以外の場合は、次の行に進んでください。

答え2

スペース以外の最初の文字の前にあるすべてのタブ文字を4つのスペースに置き換えるには、次のようにします。

perl -pe '/^(\s+)/; $k=$1; $k=~s/\t/    /g; s/^\s+/$k/'file > newfile

スクリプトは最初にすべての先行スペース(スペース、タブ、その他の項目)を見つけます$k$k$k

スペースとタブのみを制限するには:

perl -pe '/^([ \t]+)/; $k=$1; $k=~s/\t/    /g; s/^\s+/$k/'file > newfile

サンプル文字列を実行すると、これらのソリューションは次のように生成します。

$  printf '\t xxx\n   \txxx\n\t \txxx\n\tx\txx\n'  | perl -pe '/^(\s+)/; $k=$1; $k=~s/\t/    /g; s/^\s+/$k/' | od -t a
0000000  sp  sp  sp  sp  sp   x   x   x  nl  sp  sp  sp  sp  sp  sp  sp
0000020   x   x   x  nl  sp  sp  sp  sp  sp  sp  sp  sp  sp   x   x   x
0000040  nl  sp  sp  sp  sp   x  ht   x   x  nl
0000052

関連情報