我有一些由制表符或空格或两者缩进的文件。我想将前导制表符转换为空格(1 个制表符转换为 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$
正如您所看到的,原始字符串中的两个空格被简单地删除了。如何解决我的问题?我在这个网站上读过其他类似的问题,但它们与我的问题并不完全相同。
答案1
您可以使用 sed (我用来cat -T
显示文件,因为它将选项卡显示为^I
):
$ cat -T file
^I abc
^I ^Ixde^Inot
$ sed ':x;s|^\( *\)\t|\1 |;tx' file | cat -T
abc
xde^Inot
不幸的是,as 选项卡的解释\t
是 GNU sed 扩展,而不是 POSIX 指定的。但是,您可以解决这个问题printf
正如 Gilles 所示使用和写:
sed ":x;s|^\( *\)$(printf '\t')|\1 |;tx" file
sed 在那里做什么?
s|^\( *\)\t|\1 |
如果 sed 发现制表符后跟零个或多个空格字符锚定到行开头,它将用 4 个空格替换该制表符。该对\(\)
界定由 再现的匹配组(由零个或多个前面的空格字符组成)\1
。
tx
如果进行了替换,请转到标签:x
。否则,继续下一行。
答案2
要将第一个非空格字符之前的所有制表符替换为 4 个空格,请尝试:
perl -pe '/^(\s+)/; $k=$1; $k=~s/\t/ /g; s/^\s+/$k/'file > newfile
该脚本将首先找到所有前导空格(空格、制表符和其他任何内容)并将其保存为$k
.然后,它将所有制表符替换为 4 个空格,$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