awkを使用して列番号で照会する方法

awkを使用して列番号で照会する方法

,次のコマンドで区切られた列2の視差を取得したいと思います。デフォルトでは、最初の列は正常に機能します。

テーブル:

20220505,12:00:12,user,dept
20220505,12:00:25,user,dept
20220505,12:00:32,user,dept

注文する:

awk -F: '{t=$1*3600+$2*60+$3} NR>1{printf( "%.6f\n", t-p)}{p=t}' inputfile

試しましたが、正しい結果が得られませんでした。

awk -F ',' $2 '{t=$1*3600+$2*60+$3} NR>1{printf( "%.6f\n", t-p)}{p=t}' inputfile

答え1

awkに使用するように教えてください両方 ,そして、:フィールド区切り記号として使用されます。これにより、フィールド番号が変更されます(2つのフィールド区切り文字が各入力行に適用されるため)。たとえば、

$ awk -F '[:,]' '{ t = $2*3600 + $3*60 + $4 }
                 NR > 1 { printf "%.6f\n", t-p }
                 { p=t }' inputfile
13.000000
7.000000

これは、異なる日付間の視差を計算しないことに注意してください。これを行うには、結合された日付と時刻を単一のtime_t値(つまり、新起源(1970年1月1日の真夜中)以降の秒数)に解析する必要があります。例えば、牛に似た一種の栄養awk、次のmktime()機能を使用します。

$ awk -F '[:,]' '{
                    # extract the year, month, and day from the first field
                    y = substr($1,1,4);
                    m = substr($1,5,2);
                    d = substr($1,7,2);
                    # create a space-separated datespec string, combining y,m,d with
                    # hours, minutes, and seconds from fields 2, 3, and 4
                    datespec = y " " m " " d " " $2 " " $3 " " $4;
                    # convert it to seconds since the epoch
                    t = mktime(datespec)
                  }
                  NR > 1 { printf "%.6f\n", t-p }
                  { p=t }' inputfile
13.000000
7.000000

この機能の仕組みの概要を実行してman awk検索してください。mktime

答え2

使用幸せ(以前のPerl_6)

raku -e 'my @a = lines.map: *.split(",");  my @b; for ^@a.elems -> $i {  \
         my $date = @a[$i][0].subst(/ ^ (\d**4)(\d**2)(\d**2) $/, {"$0-$1-$2"});  \
         @b.push: "{$date}T@a[$i][1]Z".DateTime.Instant };  \
         loop (my $i = 0; $i < @b.elems-1; $i++) { put @b[$i+1] - @b[$i] };'

Rakuは、日付と時刻を処理するために次の方法を使用します。ISO 8601 交換規格、組み込み。最初のステートメントでは、それぞれをlinesコンマで読み取り、配列に保存します。配列が宣言されました。その後、行が繰り返され、最初の列(日付)の要素がハイフンで区切られて生成され、その文字列はISO 8601などのものを生成するために使用されます。これはすぐにオブジェクトに(秒単位で)変換され、配列に追加されます。最後のドアでは、秒が繰り返され、互いに引かれます。split","@a@bsubst-$dateDateTime2022-05-05T12:00:12ZDateTimeInstantpush@bInstantloop

入力例1:

20220505,12:00:12,user,dept
20220505,12:00:25,user,dept
20220505,12:00:32,user,dept

出力例1:

13
7

日付と時刻を使用すると、次の利点がありますISO 8601。ある日付から次の日付までのタイムスタンプを正しく処理します。

入力例2:

20220505,23:59:45,user,dept
20220506,00:00:00,user,dept
20220506,00:00:15,user,dept

出力例2:

15
15

https://en.wikipedia.org/wiki/ISO_8601
https://docs.raku.org/言語/temporal#index-entry-Date_and_time_functions
https://raku.org

関連情報