如何正确对齐多列文本文件?

如何正确对齐多列文本文件?

这是我的文件:

TLRUIDA CBdms    Status            DP  6/1/1         DC  6/1/5         0 Y
TLRUIDA CBdms    Status            DP  6/2/1         DC  6/2/5         0 Y
TLRUIDA CBdms    Status            DP  6/3/1         DC  6/3/5         0 Y
TLRUIDA CBdms    Status            DP  6/4/1         DC  6/4/5         0 Y
TLRUIDA CBdms    Status            DP  6/5/1         DC  6/5/5         0 Y
TLRUIDA CBdms    Status            DP  6/6/1         DC  6/6/5         0 Y
TLRUIDA CBdms    Status            DP  6/7/1         DC  6/7/5         0 Y
TLRUIDA CBdms    Status            DP  6/8/1         DC  6/8/5         0 Y
TLRUIDA CBdms    Status            DP  6/9/1         DC  6/9/5         0 Y
TLRUIDA CBdms    Status            DP  6/10/1         DC  6/10/5         0 Y
TLRUIDA CBdms    Status            DP  6/11/1         DC  6/11/5         0 Y
TLRUIDA CBdms    Status            DP  6/12/1         DC  6/12/5         0 Y    

我在数字 10 开始后的行中遇到对齐问题。我想要下面提到的格式,

TLRUIDA CBdms    Status            DP  6/1/1         DC  6/1/5         0 Y
TLRUIDA CBdms    Status            DP  6/2/1         DC  6/2/5         0 Y
TLRUIDA CBdms    Status            DP  6/3/1         DC  6/3/5         0 Y
TLRUIDA CBdms    Status            DP  6/4/1         DC  6/4/5         0 Y
TLRUIDA CBdms    Status            DP  6/5/1         DC  6/5/5         0 Y
TLRUIDA CBdms    Status            DP  6/6/1         DC  6/6/5         0 Y
TLRUIDA CBdms    Status            DP  6/7/1         DC  6/7/5         0 Y
TLRUIDA CBdms    Status            DP  6/8/1         DC  6/8/5         0 Y
TLRUIDA CBdms    Status            DP  6/9/1         DC  6/9/5         0 Y
TLRUIDA CBdms    Status            DP  6/10/1        DC  6/10/5        0 Y
TLRUIDA CBdms    Status            DP  6/11/1        DC  6/11/5        0 Y
TLRUIDA CBdms    Status            DP  6/12/1        DC  6/12/5        0 Y

答案1

适合这项工作的工具是column.您可以使用-o(在 OS X 上为-s)指定列分隔符,例如:

column -t -o '   ' file

给出

TLRUIDA   CBdms   Status   DP   6/1/1    DC   6/1/5    0   Y
TLRUIDA   CBdms   Status   DP   6/2/1    DC   6/2/5    0   Y
TLRUIDA   CBdms   Status   DP   6/3/1    DC   6/3/5    0   Y
TLRUIDA   CBdms   Status   DP   6/4/1    DC   6/4/5    0   Y
TLRUIDA   CBdms   Status   DP   6/5/1    DC   6/5/5    0   Y
TLRUIDA   CBdms   Status   DP   6/6/1    DC   6/6/5    0   Y
TLRUIDA   CBdms   Status   DP   6/7/1    DC   6/7/5    0   Y
TLRUIDA   CBdms   Status   DP   6/8/1    DC   6/8/5    0   Y
TLRUIDA   CBdms   Status   DP   6/9/1    DC   6/9/5    0   Y
TLRUIDA   CBdms   Status   DP   6/10/1   DC   6/10/5   0   Y
TLRUIDA   CBdms   Status   DP   6/11/1   DC   6/11/5   0   Y
TLRUIDA   CBdms   Status   DP   6/12/1   DC   6/12/5   0   Y

答案2

在这种特殊情况下,只需将所有出现的两个或多个空格更改为制表符就足够了:

sed 's/  */\t/g' file

对于更通用的解决方案,您可以使用 来确保每列都以正确的宽度打印printf。您可以直接在 shell 中执行此操作:

$ while read line; do 
    printf '%-8s%-6s%-7s%-3s%-8s%-3s%-7s%-2s%-2s\n' $line; 
done < file
TLRUIDA CBdms Status DP 6/1/1   DC 6/1/5  0 Y 
TLRUIDA CBdms Status DP 6/2/1   DC 6/2/5  0 Y 
TLRUIDA CBdms Status DP 6/3/1   DC 6/3/5  0 Y 
TLRUIDA CBdms Status DP 6/4/1   DC 6/4/5  0 Y 
TLRUIDA CBdms Status DP 6/5/1   DC 6/5/5  0 Y 
TLRUIDA CBdms Status DP 6/6/1   DC 6/6/5  0 Y 
TLRUIDA CBdms Status DP 6/7/1   DC 6/7/5  0 Y 
TLRUIDA CBdms Status DP 6/8/1   DC 6/8/5  0 Y 
TLRUIDA CBdms Status DP 6/9/1   DC 6/9/5  0 Y 
TLRUIDA CBdms Status DP 6/10/1  DC 6/10/5 0 Y 
TLRUIDA CBdms Status DP 6/11/1  DC 6/11/5 0 Y 
TLRUIDA CBdms Status DP 6/12/1  DC 6/12/5 0 Y 

或者,对于任意输入更安全:

$ while read a b c d e f g h i; do 
    printf '%-8s%-6s%-7s%-3s%-8s%-3s%-7s%-2s%-2s\n' "$a" "$b" "$c" "$d" "$e" "$f" "$g" "$h" "$i"; 
done < file
TLRUIDA CBdms Status DP 6/1/1   DC 6/1/5  0 Y 
TLRUIDA CBdms Status DP 6/2/1   DC 6/2/5  0 Y 
TLRUIDA CBdms Status DP 6/3/1   DC 6/3/5  0 Y 
TLRUIDA CBdms Status DP 6/4/1   DC 6/4/5  0 Y 
TLRUIDA CBdms Status DP 6/5/1   DC 6/5/5  0 Y 
TLRUIDA CBdms Status DP 6/6/1   DC 6/6/5  0 Y 
TLRUIDA CBdms Status DP 6/7/1   DC 6/7/5  0 Y 
TLRUIDA CBdms Status DP 6/8/1   DC 6/8/5  0 Y 
TLRUIDA CBdms Status DP 6/9/1   DC 6/9/5  0 Y 
TLRUIDA CBdms Status DP 6/10/1  DC 6/10/5 0 Y 
TLRUIDA CBdms Status DP 6/11/1  DC 6/11/5 0 Y 
TLRUIDA CBdms Status DP 6/12/1  DC 6/12/5 0 Y 

您可以使用以下方法更快更简洁地完成此操作perl

$ perl -lane 'printf "%-8s%-6s%-7s%-3s%-8s%-3s%-7s%-2s%-2s\n",@F' file
TLRUIDA CBdms Status DP 6/1/1   DC 6/1/5  0 Y 
TLRUIDA CBdms Status DP 6/2/1   DC 6/2/5  0 Y 
TLRUIDA CBdms Status DP 6/3/1   DC 6/3/5  0 Y 
TLRUIDA CBdms Status DP 6/4/1   DC 6/4/5  0 Y 
TLRUIDA CBdms Status DP 6/5/1   DC 6/5/5  0 Y 
TLRUIDA CBdms Status DP 6/6/1   DC 6/6/5  0 Y 
TLRUIDA CBdms Status DP 6/7/1   DC 6/7/5  0 Y 
TLRUIDA CBdms Status DP 6/8/1   DC 6/8/5  0 Y 
TLRUIDA CBdms Status DP 6/9/1   DC 6/9/5  0 Y 
TLRUIDA CBdms Status DP 6/10/1  DC 6/10/5 0 Y 
TLRUIDA CBdms Status DP 6/11/1  DC 6/11/5 0 Y 
TLRUIDA CBdms Status DP 6/12/1  DC 6/12/5 0 Y 

使用的好处printf是可以为每列指定最小列宽。这意味着如果您的其中一列可以具有更长的值,它仍然可以工作。例如,如果其中一行的第一个字段可能是averylongfieldindeed,则可以将第一列的最小宽度设置为 21 并对齐输出:

$ perl -lane 'printf "%-21s%-6s%-7s%-3s%-8s%-3s%-7s%-2s%-2s\n",@F' file
averylongfieldindeed CBdms Status DP 6/1/1   DC 6/1/5  0 Y 
TLRUIDA              CBdms Status DP 6/2/1   DC 6/2/5  0 Y 
TLRUIDA              CBdms Status DP 6/3/1   DC 6/3/5  0 Y 
TLRUIDA              CBdms Status DP 6/4/1   DC 6/4/5  0 Y 
TLRUIDA              CBdms Status DP 6/5/1   DC 6/5/5  0 Y 
TLRUIDA              CBdms Status DP 6/6/1   DC 6/6/5  0 Y 
TLRUIDA              CBdms Status DP 6/7/1   DC 6/7/5  0 Y 
TLRUIDA              CBdms Status DP 6/8/1   DC 6/8/5  0 Y 
TLRUIDA              CBdms Status DP 6/9/1   DC 6/9/5  0 Y 
TLRUIDA              CBdms Status DP 6/10/1  DC 6/10/5 0 Y 
TLRUIDA              CBdms Status DP 6/11/1  DC 6/11/5 0 Y 
TLRUIDA              CBdms Status DP 6/12/1  DC 6/12/5 0 Y 

相比之下,使用选项卡是行不通的:

$ sed  -e "s/\s\+/\t/g" file
averylongfieldindeed    CBdms   Status  DP  6/1/1   DC  6/1/5   0   Y
TLRUIDA CBdms   Status  DP  6/2/1   DC  6/2/5   0   Y
TLRUIDA CBdms   Status  DP  6/3/1   DC  6/3/5   0   Y
TLRUIDA CBdms   Status  DP  6/4/1   DC  6/4/5   0   Y
TLRUIDA CBdms   Status  DP  6/5/1   DC  6/5/5   0   Y
TLRUIDA CBdms   Status  DP  6/6/1   DC  6/6/5   0   Y
TLRUIDA CBdms   Status  DP  6/7/1   DC  6/7/5   0   Y
TLRUIDA CBdms   Status  DP  6/8/1   DC  6/8/5   0   Y
TLRUIDA CBdms   Status  DP  6/9/1   DC  6/9/5   0   Y
TLRUIDA CBdms   Status  DP  6/10/1  DC  6/10/5  0   Y
TLRUIDA CBdms   Status  DP  6/11/1  DC  6/11/5  0   Y
TLRUIDA CBdms   Status  DP  6/12/1  DC  6/12/5  0   Y   

答案3

此 sed 命令修复给定的输出:

sed 's=\(D[CP] *./../.\) =\1=g'

./../.它在 DC 和 DP 之后删除一个空格。如果其他数字也可以变得更长,那么 sed 可能不是适合这项工作的工具。

答案4

我们有一个非常简单的命令:

tr -s ' ' <input-file >output-file

-s选项删除出现的<space>(或与此相关的命令行上其后的任何字符)

相关内容