如何使用 sed 将前导制表符替换为 4 个空格?

如何使用 sed 将前导制表符替换为 4 个空格?

在 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

相关内容