Trying to sort lines in a file. The column1 is HH:MM:SS format and col2 is AM/PM. Need to arrange lines from AM to PM firstly and then progressive time.
Current :
11:36:48 AM col3 ...
11:32:00 AM col3 ...
03:18:54 PM col3 ...
02:26:40 PM col3 ...
01:51:56 PM col3 ...
12:55:58 PM col3 ...
11:58:48 AM col3 ...
09:38:41 AM col3 ...
Final:
09:38:41 AM col3 ...
11:32:00 AM col3 ...
11:36:48 AM col3 ...
11:58:48 AM col3 ...
12:55:58 PM col3 ...
01:51:56 PM col3 ...
02:26:40 PM col3 ...
03:18:54 PM col3 ...
Thanks
CodePudding user response:
All you have to do is get the AM lines with grep
, then use sort
on the output. After doing that then you can do the same for the PM lines.
cp "my_file" "backup_file" #Backup old file before overwriting
grep '^[0-9:]* AM' "backup_file" | sort > "my_file"
grep '^[0-9:]* PM' "backup_file" | sort >> "my_file"
Its important to backup your file before using >
operation since that will completely overwrite your file.
CodePudding user response:
A Schwartzian transform:
while read -ra fields; do
printf '%s\t%s\n' "$(date -d "${fields[*]:0:2}" ' %s')" "${fields[*]}"
done < input \
| sort -n \
| cut -f 2-
outputs
09:38:41 AM col3 ...
11:32:00 AM col3 ...
11:36:48 AM col3 ...
11:58:48 AM col3 ...
12:55:58 PM col3 ...
01:51:56 PM col3 ...
02:26:40 PM col3 ...
03:18:54 PM col3 ...
The while loop calculates the epoch time for each timestamp and adds it to the output stream. Then it gets sorted by the numeric time. Then that field is removed.
Doing this in bash may be slower than doing it in, say, perl:
perl -MTime::Piece -lane '
push @lines, [@F];
} END {
print join "\n",
map {"@{$_->[1]}"}
sort {$a->[0] <=> $b->[0]}
map {[Time::Piece->strptime("$_->[0] $_->[1]", "%T %p")->epoch, $_]}
@lines;
' input