4

入力

2012-07-24 10:05:08 AM
2012-07-26 10:13:58 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM

望ましい出力

2012-07-24 10:05:08 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
2012-07-26 10:13:58 AM

試したコード

 sort -t ":" -k 1 -k 2 -k 3 Input.txt | sort -t " " -k 3

しかし、私は望ましい出力を得ていません。

誰でも何か提案できますか?


コードを書きました...それでも問題は解決しません...

コード

 sed 's/ 12:/00:/g' Input.txt | sort -k 1,1 -k 3,3 -k 2,2 | sed 's/00:/12:/g'

最初に12:43:01 AM00:43:01 AM に変更してから、sort コマンドを適用します。

4

9 に答える 9

4

ソートのためにエポック秒に変換

データが /tmp/foo に保存されていると仮定すると、タイムスタンプを GNU 日付で数値的にソート可能な形式に変換できます。例えば:

date -f /tmp/foo '+%s' | sort |
while read; do
    date -d "@$REPLY" "+%F %I:%M:%S %p"
done

これにより、すべてのケースでソートが正しく処理されます。特に、すべての AM 時間が同じ日付のすべての PM 時間の前に来る必要がある場合です。たとえば、午前 12:01 は、午後 10:00 より前に表示されるようになりました。

于 2012-07-25T13:15:13.813 に答える
3

文字列は、12時間の時間を除いて、単純に字句的に並べ替えることができます。

このソリューションでは、シュワルツ変換を使用して、文字列の並べ替えに使用されるキーを変更します。で終わる文字列の時間フィールドに12を追加しPM、代わりにそれで並べ替えます。

use strict;
use warnings;

my @data = <DATA>;
chomp @data;

my @sorted = map $_->[0],
sort { $a->[1] cmp $b->[1] }
map { (my $dt = $_) =~ s/(\d\d)(?=:\d\d:\d\d PM)/$1+12/e; [$_, $dt] } @data;

print "$_\n" for @sorted;


__DATA__
2012-07-24 10:05:08 AM
2012-07-26 10:13:58 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM

出力

2012-07-24 10:05:08 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
2012-07-26 10:13:58 AM

アップデート

steffenが指摘しているように、午前/午後の時間を調整した後でも、真夜中と正午は単純な文字列の並べ替えが機能しません。

このプログラムは、コアモジュールを使用して、字句的に並べ替えることができるTime::PieceISO8601形式2000-02-29T12:34:56で日付/時刻を再フォーマットします。

use strict;
use warnings;

use Time::Piece;

my @data = <DATA>;
chomp @data;

my @sorted = map $_->[0],
sort { $a->[1] cmp $b->[1] }
map { [ $_, toISO8601($_) ] } @data;

sub toISO8601 {
  Time::Piece->strptime(@_, '%Y-%m-%d %I:%M:%S %p')->datetime;
}

print "$_\n" for @sorted;

__DATA__
2012-07-24 10:05:08 AM
2012-07-26 10:13:58 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
2012-08-01 01:00:00 PM
2012-08-01 12:30:00 PM
2012-08-01 12:00:00 PM
2012-08-01 11:30:00 AM
2012-08-01 01:00:00 AM
2012-08-01 12:30:00 AM
2012-08-01 12:00:00 AM

出力

2012-07-24 10:05:08 AM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
2012-07-26 10:13:58 AM
2012-08-01 12:00:00 AM
2012-08-01 12:30:00 AM
2012-08-01 01:00:00 AM
2012-08-01 11:30:00 AM
2012-08-01 12:00:00 PM
2012-08-01 12:30:00 PM
2012-08-01 01:00:00 PM
于 2012-07-25T10:10:15.733 に答える
2

シャルツ 変換Date::Parseの使用:

use strict;
use warnings;
use 5.010;
use Date::Parse;

my @data = <DATA>;
chomp @data;

my @sorted = 
    map  { $_->[0] }
    sort { $a->[1] <=> $b->[1] }
    map  { [$_, str2time($_)] } @data;

say for @sorted;

__DATA__
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 01:26:08 PM
2012-07-25 12:26:08 PM
2012-07-25 01:26:08 AM
2012-07-25 12:26:08 AM
2012-07-25 11:26:08 AM
2012-07-25 11:26:08 PM

出力:

2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 12:26:08 AM
2012-07-25 01:26:08 AM
2012-07-25 11:26:08 AM
2012-07-25 12:26:08 PM
2012-07-25 01:26:08 PM
2012-07-25 11:26:08 PM
于 2012-07-25T12:52:21.900 に答える
2

少しawk病棟、私は認めます...

猫の入力.txt | \ awk 'BEGIN{FS="[: -]"}{if($7 == "PM") $4+=12; print $1"-"$2"-"$3" "$4":"$5":"$6" "$7}'|\ sort|\ awk 'BEGIN{FS="[: -]"}{if($7 == "午後") $4-=12; print $1"-"$2"-"$3" "$4":"$5":"$6" "$7}'

編集:

cat Input.txt |\
awk 'BEGIN{FS="[: -]"}{if(length($4)==1) $4="0"$4 ;if($7 == "PM") $4+=12; else if($4 ==12)$4-=12; print $1"-"$2"-"$3" "$4":"$5":"$6" "$7}'|\
sort|\
awk 'BEGIN{FS="[: -]"}{if($7 == "PM") $4-=12; else if($4 ==0)$4+=12; print $1"-"$2"-"$3" "$4":"$5":"$6" "$7}'

しかし、それは動作します...

説明: を使用して時刻形式を 24 時間形式に変換しawk、並べ替えて元に戻します。

編集:正しく並べ替える0ために、1 桁だけを a から時間1:0:0の前に追加します。12:0:0AM用もあります。

于 2012-07-25T09:11:56.580 に答える
1

午前 12 時 1 分は午前 1 時 1 分よりも前に来るため、並べ替えだけでどのように役立つかわかりません。

テキストまたは数値として比較できるものを取得するには、ISO 8601 または秒数など、他の形式に変換する必要があります。perl ワンライナーがそれを行います。

于 2012-07-25T08:32:50.423 に答える
1

これを使用できます:

sed 's/ 12:/ 00:/'| LC_ALL="C" sort -k 1,1 -k 3 | sed 's/ 00:/ 12:/'

それはかなり速い解決策になるはずです。

于 2012-07-25T22:14:40.487 に答える
0

これはあなたのために働くかもしれません(GNU sed):

sed 's/.*/echo -e "$(date -d"&" +%s)\t&"/e' file | sort -n | sed 's/.*\t//'

また:

date -f file +%s | paste - file | sort -n | sed 's/\S\+\s\+//'
于 2012-07-25T15:24:59.713 に答える
0

私の変種があります:

$sed 's|\([0-9]\+\)-\([0-9]\+\)-\([0-9]\+\) \([0-9]\+\):\([0-9]\+\):\([0-9]\+\) \([A-Z]\+\)|\1 \2 \3 \4 \5 \6 \7 \0|' input.txt | awk '{if($7=="AM"){$7="1";if($4==12){$4 = 0}}else{$7="0"};print}' | sort -n -k1 -k2 -k3 -k4 -k5 -k6 -k7 | cut -d' ' -f 8-
2012-07-24 10:05:08 PM
2012-07-24 10:13:58 AM
2012-07-24 10:57:50 AM
2012-07-24 11:15:03 AM
2012-07-24 11:26:08 PM
2012-07-25 11:26:08 PM
2012-07-26 10:13:58 AM

余分なフィールドを追加し、それらをソートし、ソート後にそれらを取り除くという主なアイデア。数値の並べ替えは簡単ですが、AM/PM を並べ替えるには、並べ替えを簡単にするために 1/0 の数字に変換します。

更新: sed+awk使用法は次のように置き換えることができますawk:

awk -F'[-: ]' '{printf("%d %d %d %d %d %d %d %s\n", $1, $2, $3, ($4 == 12 && $7 == "AM" ? 0 : $4), $5, $6, $7 == "AM", $0)}' input.txt |
sort -n -k1 -k2 -k3 -k4 -k5 -k6 -k7 |
cut -d' ' -f 8-

更新: AM/PM の問題を修正

于 2012-07-25T09:43:29.787 に答える
-1

最後に、外部モジュールを使用せずにコーディングしました。長いですが、どの日付形式でもスムーズに動作します。

使用される技術:

  1. 最初にファイル内の各日付をそのタイムスタンプに変換します
  2. タイムスタンプを数字のままソートします。
  3. 再度、スカラー localtime を使用してタイムスタンプを日付に変換します。

コード

my @input = `cat Input.txt`;

    open (ts,">","tt.txt");
    foreach my $i (@input)
    {
            chomp($i);
            my $timestamp = `date --date "$i" +\%s`;
            chomp($timestamp);
            push (@time,$timestamp);
            print ts "$timestamp\n";
    }
    close(ts);

    open (ts,">","sort_time.txt");
    my @sorted_time = join "\n",sort {$a<=>$b} @time;
    chomp(@sorted_time);
    print ts "@sorted_time\n";
    close(ts);

    my @input1=  `cat sort_time.txt`;
    open (ts,">","sort_timestamp.txt");
    foreach my $st1 (@input1)
    {
            chomp($st1);
            my $st2 = scalar localtime($st1);
            chomp($st2);
            print ts "$st2\n";
    }
    close(ts);



    @input2 = `cat sort_timestamp.txt`;
    open (ts,">","Output.txt");
    foreach my $st2 (@input2)
    {
            chomp($st2);
            $pro_time = `date --date "$st2" +\%Y-\%m-\%d~\%r | sed 's/~/ /g'`;
            chomp($pro_time);
            print ts "$pro_time\n";
    }
    close(ts);


    `rm tt.txt sort_time.txt sort_timestamp.txt`;
于 2012-07-27T07:01:18.797 に答える