複数列のテキストファイルを正しくソートする方法は?

複数列のテキストファイルを正しくソートする方法は?

これは私のファイルです:

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

操作に適したツールは、次のように(OS Xで)を使用して列区切り文字を指定columnできます。-o-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

この特別なケースでは、2つ以上のスペースをすべてタブに変更するだけで十分です。

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

より一般的な解決策を使用すると、各列が正しい幅で印刷されるようにすることができますprintf。シェルから直接これを行うことができます。

$ 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これにより、各列の最小列幅を指定できるという利点があります。これは、列の1つがより長い値を持つことができても、まだ機能することを意味します。たとえば、行の1つの最初のフィールドがある場合は、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>(またはコマンドラインからそれに続くすべての文字)を削除します。

関連情報