在 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
)。他们还可以选择仅转换初始的、前导的空格/制表符。有关详细信息,请参阅手册页。
有关 的更多信息sponge
,请参阅man sponge
和是否有标准的替代海绵来将文件传输到自身中?。简而言之,它使用临时文件为您执行重定向和 mv。顺便说一句,永远不要尝试将标准输出重定向到当前用作标准输入的同一文件。 shell 会在读取之前覆盖它。
sponge
是来自更多实用程序包裹。
PS:另请参阅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