Sed

如何僅替換前導製表符(包括一些空格字元後的製表符)?

  • May 13, 2020

我有一些由製表符或空格或兩者縮進的文件。我想將前導製表符轉換為空格(一個製表符轉換為 4 個空格)。這包括一些前導空格後的製表符。以下是一些輸入行和預期結果的一些範例。

+-----+---------------+-----------------+
| 沒有。原線 | 預期結果 |
+-----+---------------+-----------------+
| 1 | \t␣xxx | ␣␣␣␣␣xxx |
| 2 | ␣␣␣ \ txxx | ␣␣␣␣␣␣␣xxx |
| 3 | \t␣\txxx | ␣␣␣␣␣␣␣␣␣xxx |
| 4 | \tx\txx | ␣␣␣␣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$ 

如您所見,原始字元串中的兩個空格被簡單地刪除了。如何解決我的問題?我在這個網站上閱讀了其他類似的問題,但它們與我的問題並不完全相同。

您可以使用 sed (我cat -T用來顯示文件,因為它顯示選項卡為^I):

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

不幸的是,\tas tab 的解釋是 GNU sed 擴展,而不是 POSIX 指定的。但是,您可以使用printfGilles 在此處顯示的內容來解決此問題並編寫:

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

sed 在那裡做什麼?

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

如果 sed 發現一個製表符後跟零個或多個定位到行首的空格字元,它會將製表符替換為 4 個空格。該對\(\)劃定由 複製的匹配組(由零個或多個前面的空格字元組成)\1

  • tx

如果進行了替換,請轉到 label :x。否則,繼續下一行。

引用自:https://unix.stackexchange.com/questions/586326