![将缩进选项卡替换为每个选项卡固定数量的空格](https://linux22.com/image/150825/%E5%B0%86%E7%BC%A9%E8%BF%9B%E9%80%89%E9%A1%B9%E5%8D%A1%E6%9B%BF%E6%8D%A2%E4%B8%BA%E6%AF%8F%E4%B8%AA%E9%80%89%E9%A1%B9%E5%8D%A1%E5%9B%BA%E5%AE%9A%E6%95%B0%E9%87%8F%E7%9A%84%E7%A9%BA%E6%A0%BC.png)
是否可以仅用每个选项卡的一定数量的空格替换“前导选项卡”?我将前导制表符定义为前面仅包含制表符或空格的制表符。我将前导或缩进制表符定义为仅前面有空格的制表符。
我的以下行.nexrc
抄袭自这个。它通过过滤器运行包含标记的行a
和标记之间的行。b
取代选项卡。
map \2 'a!'b pr -te2
但是,它很好地用两个空格替换了非前导制表符,这并不理想,因为有时需要文字制表符。
是否有一种简单且可移植的方法来仅用每个选项卡一定数量的空格替换前导选项卡?
下面的 perl 脚本(可以折叠为一行)的工作是用命令行上提供的宽度替换前导制表符,但它依赖于 Perl 的可用性,并且需要二次时间(如果文件不包含任何内容)但选项卡)。
#!/usr/bin/env perl
use strict;
use warnings;
my ($width) = @ARGV;
$width //= 2;
my $replacement = ' ' x $width;
while (<>) {
while (s/^(\s*)\t/$1$replacement/g) { }
print;
}
这是我想要发生的事情的一个例子。^I
指制表符字节,#
是行开头的零宽度标记。下面的行是字节标尺。
前:
#^I^I ^Ia^Ib
# 1 23 45 67
之后(制表符宽度为 2)
# a^Ib
#12345678 90
之后(制表符宽度为 4)
# a^Ib
#12345678901234 56
答案1
如果您正在寻找使用其他命令行工具的通用解决方案,可以使用Awk
此工具。
var=$'\t\t\tnewcontent'
echo "$var" | awk '{ gsub(/^[\t]+/," ",$0) }1'
上面的命令将再出现一次 替换为Tab单个空格,即 中的第二个参数gsub
。您可以通过生成所需的空间数量来使其可配置
awk -v n=5 ' BEGIN{ spaces = sprintf("%"n"s"," ") }{ gsub(/^[\t]+/,spaces,$0) }1'
从上次更新来看,OP似乎想用找到的确切空格数替换前导制表符的数量,
awk -F$'\t' '{ spaces = sprintf("%"(NF-1)"s"," "); gsub(/^[\t]+/,spaces,$0) }1'
逻辑是通过将字段分隔符设置为\t
,可以通过执行来识别前导制表符的数量NF-1
。确定前导制表符的数量后,使用它来生成与早期sprintf()
方法相同数量的空格。
验证hexdump -C
更换前后就可以看到
echo "$var" | hexdump -C
00000000 09 09 09 6e 65 77 63 6f 6e 74 65 6e 74 0a |...newcontent.|
0000000e
现在更换
echo "$var" | awk -F$'\t' '{ spaces = sprintf("%"(NF-1)"s"," "); gsub(/^[\t]+/,spaces,$0) }1' | hexdump -C
00000000 20 20 20 6e 65 77 63 6f 6e 74 65 6e 74 0a | newcontent.|
0000000e