Reputation: 95
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?
Upvotes: 3
Views: 2750
Reputation: 185881
With a short Perl one-liner:
perl -anE 'say join " ", @F[1..$#F,0]' file
@F
is the array fed by (auto)split on spaces (by default, like awk
) with the -a
switch1..$#F,0
is an array sliceUpvotes: 0
Reputation: 37464
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
Upvotes: 4
Reputation: 92904
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
Upvotes: 7
Reputation: 204731
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
Upvotes: 4
Reputation: 133780
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
Upvotes: 2
Reputation: 247250
Perl is handy for text manipulation:
perl -lane 'push @F, shift @F; print "@F"' file
Upvotes: 5