Shell
如何正確對齊多列文本文件?
這是我的文件:
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
適合這項工作的工具是
column
.-o
您可以使用(on OS X it’s )指定列分隔符-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
在這種特殊情況下,只需將所有出現的兩個或多個空格更改為一個製表符就足夠了:
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