How to move first column to last column in unix?

淺唱寂寞╮ 提交于 2021-02-05 06:37:26

问题


This is the data in a text file.

0.354167 male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50
0.625 male typ_angina 0.792453 0.328767 f left_vent_hyper 0.564885 no 0.677419 down 0 reversable_defect <50
0.645833 male non_anginal 0.433962 0.134703 f left_vent_hyper 0.641221 no 0.483871 flat 0 normal >50_1
0.666667 female asympt 0.481132 0.413242 f left_vent_hyper 0.572519 yes 0.16129 flat 0 reversable_defect >50_1
0.270833 male typ_angina 0.509434 0.269406 f left_vent_hyper 0.816794 no 0.129032 up 0.666667 normal <50

I have to move first column contains numeric data to the last column for every row.

For eg:

0.354167 male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50

TO

male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50 0.354167

How can I do using bash commands?


回答1:


Perl is handy for text manipulation:

perl -lane 'push @F, shift @F; print "@F"' file



回答2:


Short awk solution (without loop though all fields):

awk '{ $(NF+1)=$1; sub(/^[^ ]+ */,"") }1' file.txt
  • $(NF+1)=$1 - append the 1st field to the end (as the last field)

  • sub(/^[^ ]+ */,"") - remove the 1st field with following space(s)


The output:

male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50 0.354167
male typ_angina 0.792453 0.328767 f left_vent_hyper 0.564885 no 0.677419 down 0 reversable_defect <50 0.625
male non_anginal 0.433962 0.134703 f left_vent_hyper 0.641221 no 0.483871 flat 0 normal >50_1 0.645833
female asympt 0.481132 0.413242 f left_vent_hyper 0.572519 yes 0.16129 flat 0 reversable_defect >50_1 0.666667
male typ_angina 0.509434 0.269406 f left_vent_hyper 0.816794 no 0.129032 up 0.666667 normal <50 0.270833



回答3:


Since this is a simple substitution on individual lines, it's a perfect job for sed:

$ sed 's/\([^ ]*\) \(.*\)/\2 \1/' file
male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50 0.354167
male typ_angina 0.792453 0.328767 f left_vent_hyper 0.564885 no 0.677419 down 0 reversable_defect <50 0.625
male non_anginal 0.433962 0.134703 f left_vent_hyper 0.641221 no 0.483871 flat 0 normal >50_1 0.645833
female asympt 0.481132 0.413242 f left_vent_hyper 0.572519 yes 0.16129 flat 0 reversable_defect >50_1 0.666667
male typ_angina 0.509434 0.269406 f left_vent_hyper 0.816794 no 0.129032 up 0.666667 normal <50 0.270833



回答4:


In awk. Straightforward, find the first space, `print after it and before it:

$ awk '{
    match($0," ")                                         # find space
    print substr($0,RSTART+RLENGTH),substr($0,1,RSTART)   # print around it
}' file
male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50 0.354167 
male typ_angina 0.792453 0.328767 f left_vent_hyper 0.564885 no 0.677419 down 0 reversable_defect <50 0.625 
...

or the play with the fields: Store the first field to t then starting from the first field replace it with the next field. Replace the last field with the t:

$ awk '{t=$1;for(i=1;i<NF;i++)$i=$(i+1);$NF=t}1' file
male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50 0.354167
...

Explained:

$ awk ' 
{
    t=$1               # store 1st to t
    for(i=1;i<NF;i++)  # iterate all but the last field
        $i=$(i+1)      # replacing with the next
    $NF=t              # then the last is replaced with t
}1                     # output
' file



回答5:


Following awk will fulfill your question.

Solution 1st:

awk '{for(i=2;i<=NF;i++){printf("%s%s",$i,i==NF?" "$1"\n":" ")}}'   Input_file

Output will be as follows.

male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50 0.354167

Explanation: Traversing through all the fields starting from 2nd field to NF(total number of fields) value. Here I am using printf to print the values so there are 2 strings which I am looking to print 1st is off course field's value and second is to check if variable i's value is equal to NF means we reached to last field then print space first field and new line(as per OP's request) else(if i's value is NOT equal to NF) then print simple space.

EDIT: I ran my command to complete Input_file too now and seems to be fine as follows is the output.

awk '{for(i=2;i<=NF;i++){printf("%s%s",$i,i==NF?" "$1"\n":" ")}}'  Input_file
male atyp_angina 0.066038 0.1621 t normal 0.648855 no 0 up 0 reversable_defect <50 0.354167
male typ_angina 0.792453 0.328767 f left_vent_hyper 0.564885 no 0.677419 down 0 reversable_defect <50 0.625
male non_anginal 0.433962 0.134703 f left_vent_hyper 0.641221 no 0.483871 flat 0 normal >50_1 0.645833
female asympt 0.481132 0.413242 f left_vent_hyper 0.572519 yes 0.16129 flat 0 reversable_defect >50_1 0.666667
male typ_angina 0.509434 0.269406 f left_vent_hyper 0.816794 no 0.129032 up 0.666667 normal <50 0.270833


来源:https://stackoverflow.com/questions/46546890/how-to-move-first-column-to-last-column-in-unix

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!