如何将制表符转换为一个目录的每个文件中的空格(可能递归)?

此外,是否有一种方法来设置每个制表符的空格数?


当前回答

没有人提到rpl?使用rpl可以替换任何字符串。 要将制表符转换为空格,

rpl -R -e "\t" "    "  .

非常简单。

其他回答

在其他答案中建议的使用expand似乎是仅用于此任务的最合乎逻辑的方法。

也就是说,它也可以用Bash和Awk来完成,以防你想在它的同时做一些其他的修改。

如果使用Bash 4.0或更高版本,shopt内置的globstar可以使用**进行递归搜索。

在GNU Awk 4.1或更高版本中,sed可以像“inplace”一样修改文件:

shopt -s globstar
gawk -i inplace '{gsub("\t","    ")}1' **/*.ext

如果你想设置每个制表符的空格数:

gawk -i inplace -v n=4 'BEGIN{for(i=1;i<=n;i++) c=c" "}{gsub("\t",c)}1' **/*.ext

您可以使用find与制表符到空格包。

首先,安装制表符到空格

npm install -g tabs-to-spaces

然后,从项目的根目录运行这个命令;

find . -name '*' -exec t2s --spaces 2 {} \;

这将把每个文件中的每个制表符替换为2个空格。

尝试命令行工具expand。

expand -i -t 4 input | sponge output

在哪里

-i用于只展开每行的前导制表符; -t 4表示每个制表符将转换为4个空格字符(默认为8个)。 Sponge来自moreutils包,避免清除输入文件。在macOS上,moreutils包可以通过Homebrew (brew install moreutils)或MacPorts (sudo port install moreutils)获得。

最后,在使用Homebrew (brew install coreutils)或MacPorts (sudo port install coreutils)安装coreutils之后,可以在macOS上使用gexpand。

对于递归应用程序,我喜欢上面的“find”示例。为了使其具有非递归性,只更改当前目录中匹配通配符的文件,shell glob扩展可以满足少量文件的需求:

ls *.java | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh -v

如果在您相信它工作之后希望它保持沉默,只需在sh命令的末尾加上-v。

当然,您可以在第一个命令中选择任何一组文件。例如,以受控的方式只列出一个特定的子目录(或多个目录),如下所示:

ls mod/*/*.php | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh

或者反过来运行find(1)与深度参数等的一些组合:

find mod/ -name '*.php' -mindepth 1 -maxdepth 2 | awk '{print "expand -t 4 ", $0, " > /tmp/e; mv /tmp/e ", $0}' | sh

使用vim-way:

$ ex +'bufdo retab' -cxa **/*.*

做备份!在执行上述命令之前,因为它可能损坏您的二进制文件。 要使用globstar(**)进行递归,请通过shop -s globstar激活。 指定特定的文件类型,例如:**/*.c。

修改制表符,添加+'set ts=2'。

然而,缺点是它可以替换字符串中的制表符。

因此,为了更好的解决方案(使用代换法),尝试:

$ ex -s +'bufdo %s/^\t\+/  /ge' -cxa **/*.*

或者使用ex编辑器+扩展实用程序:

$ ex -s +'bufdo!%!expand -t2' -cxa **/*.*

有关尾随空格,请参见:如何为多个文件删除尾随空格?


你可以在你的.bash_profile中添加以下函数:

# Convert tabs to spaces.
# Usage: retab *.*
# See: https://stackoverflow.com/q/11094383/55075
retab() {
  ex +'set ts=2' +'bufdo retab' -cxa $*
}