1

I've got a number of .dat files (variable) with 2 pieces of information in them each, a weight and a height, space delimited like the following where First_Last is a name:

18kg 1.2m in "First1_Last1.dat"

12kg 1.6m in "First2_Last2.dat" etc.

I need to sort them by either the first or second value in each. I'm thinking the I have to cat and combine all the files, strip the units out with a cut (not so sure on that), then add the filenames as a third column using paste and finally sort -k 1,1 temp.txt on my temporary file to get my desired output while still being able to keep track of which file each value came from because I need the associated names to open a different file for each person in the correct order after. So my output file I would use would look something like

12 1.6 First2_Last2.dat
18 1.2 First1_Last1.dat

I'm wondering if there is a better way to do this using something built in or a property of the .dat file type I'm missing. Or maybe using awk?

0

If your files only contain one datum (line) each, something as simple as this might work:

for x in *.dat ; do     
    echo $(< "$x") $x    # print contents of file and add the filename 
done  |  sort -nsk2,2    # stable sort by the second column.

I tested quickly with GNU sort, and didn't really see the units or decimals giving problems, but I make no guarantees.

  • Your sort command doesn't sort by just the first column. You need -k1,1 for that since sort defaults to the end of the line if POS2 is omitted. – maxschlepzig Oct 3 '16 at 11:40
  • @maxschlepzig, ah, might be. Though I've have a hard time seeing that as much of a problem. If it matters, we'd better ask for a stable sort too. – ilkkachu Oct 3 '16 at 11:49
  • well, at least the comment in your shell snippet doesn't match the code - also, if it doesn't matter why do you include -k1 at all? – maxschlepzig Oct 3 '16 at 11:54
  • Thanks this turned out to be the simplest with where I'm at in shell scripting, also did need stable sort for whatever reason to get the right sort with the units still there. – Matt Ruth Oct 3 '16 at 16:10
1

You can use grep and sed to extract the sort key and specify only certain columns for sorting:

grep -H kg *.dat \
  | sed 's/^\([^:]\+\):\([0-9.]\+\)kg \+\([0-9.]\+\)m.*$/\2 \3 \1/' \
  | sort -t' ' -k1,2 -g

Example output:

12 1.6 First2_Last2.dat
18 1.2 First1_Last1.dat
  • Thanks for the answer, I don't have enough experience with the sed command so I'll be using this to help get more familiar with what it can do – Matt Ruth Oct 3 '16 at 16:36
0

Maybe using (a recent version of) GNU awk - assuming that by ".dat file" you just mean a whitespace-delimited text file:

awk -v sort=2 '
  {
    gsub(/kg|m/,"",$0);
    a[$sort]=$0 FS FILENAME;
  }
  END {
    PROCINFO["sorted_in"]="@ind_num_asc";
    for (i in a) print a[i];
  }' *.dat

where the variable sort sets the column to sort on (1 or 2); or as a one-liner

awk -v sort=1 '{gsub(/kg|m/,"",$0); a[$sort]=$0 FS FILENAME}; END{PROCINFO["sorted_in"]="@ind_num_asc"; for (i in a) print a[i]}' *.dat

Testing

$ awk -v sort=1 '{gsub(/kg|m/,"",$0); a[$sort]=$0 FS FILENAME}; END{PROCINFO["sorted_in"]="@ind_num_asc"; for (i in a) print a[i]}' *.dat
12 1.6 First2_Last2.dat
18 1.2 First1_Last1.dat

and

$ awk -v sort=2 '{gsub(/kg|m/,"",$0); a[$sort]=$0 FS FILENAME}; END{PROCINFO["sorted_in"]="@ind_num_asc"; for (i in a) print a[i]}' *.dat
18 1.2 First1_Last1.dat
12 1.6 First2_Last2.dat

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.