次の形式のレコードを含むファイルがあります:
D20220327,S2927,977,1
D20220328,S2927,977,1
D20220329,S2927,977,1
D20220330,S2927,977,1
D20220331,S2927,977,1
D20220401,S2927,977,1
D20220402,S2927,977,1
D20220403,S2927,977,1
D20220404,S2927,977,1
しかし、これらを7日前にシフトする変換を適用した後、3月28日から4月3日までの日付では機能しません。ただし、同じコードロジックは3月27日と4月4日には正常に機能します。なぜこれが1週間だけ機能しないのかわかりません。これが出力です。
D20220320,S2927,977,1 -- correct
D20220320,S2927,977,1 -- incorrect
D20220321,S2927,977,1 -- incorrect
D20220322,S2927,977,1 -- incorrect
D20220323,S2927,977,1 -- incorrect
D20220324,S2927,977,1 -- incorrect
D20220325,S2927,977,1 -- incorrect
D20220326,S2927,977,1 -- incorrect
D20220328,S2927,977,1 -- correct
ここで使用されるロジックは次のとおりです:
BEGIN {
OFS = FS = ","
}
{
t = mktime(sprintf("%4d %.2d %.2d 00 00 00",
substr($1,2,4),
substr($1,6,2),
substr($1,8,2)));
$1 = substr($1,1,1) strftime("%Y%m%d", t - 7*24*60*60)
print
}
答え1
計算は現地時間で行われ、3 月 27 日の夏時間への切り替えの影響を受けます。
代わりに UTC 時間で計算を行うには (Unix タイムスタンプはローカル時間ではありません)、GNU の最新リリースを使用して、最後の引数として をawk
必ず渡してください。1
mktime()
t = mktime(sprintf("%4d %.2d %.2d 00 00 00",
substr($1,2,4),
substr($1,6,2),
substr($1,8,2)), 1);
awk
これは、GNUawk
リリース 4.2.0 以降で利用可能なGNU 拡張機能です。
代わりに、午前 0 時 (UTC) 付近の時刻を参照時刻として使用しないようにすることもできます。
t = mktime(sprintf("%4d %.2d %.2d 12 00 00",
substr($1,2,4),
substr($1,6,2),
substr($1,8,2)));
これにより、古い GNU 実装や、必要な機能を備えたawk
その他の実装でも動作するようになります。awk
さらに別の方法としては、変更されたローカル タイム ゾーンでスクリプトを実行することです。
TZ=UTC awk -f script.awk inputfile
これにより、スクリプトの実行用にTZ
環境変数が に設定され、および関連関数で使用されるタイムゾーンが変更されます。UTC
awk
mktime()
答え2
Raku (旧称 Perl_6) の使用
raku -pe 's/^ D <( (\d**4)(\d**2)(\d**2) )> \, /{ "$0-$1-$2".Date.earlier(:7days).Str.subst("-", :g); }/;'
サンプル入力(空白行は削除されています):
D20220327,S2927,977,1
D20220328,S2927,977,1
D20220329,S2927,977,1
D20220330,S2927,977,1
D20220331,S2927,977,1
D20220401,S2927,977,1
D20220402,S2927,977,1
D20220403,S2927,977,1
D20220404,S2927,977,1
サンプル出力:
D20220320,S2927,977,1
D20220321,S2927,977,1
D20220322,S2927,977,1
D20220323,S2927,977,1
D20220324,S2927,977,1
D20220325,S2927,977,1
D20220326,S2927,977,1
D20220327,S2927,977,1
D20220328,S2927,977,1
簡単に言うと、Raku の行単位 (自動印刷)-pe
フラグが、使い慣れた演算子と組み合わせて使用されますs///
。数字は、括弧で囲まれた一致変数$0
、$1
、$2
にキャプチャされ、キャプチャ マーカーを<( … )>
使用して一致のその他のすべての要素が削除されます。
置換では、Raku は{ … }
ブロック内のコードを実行します。$0
、、$1
および$2
キャプチャは適切なダッシュ ( -
) で文字列化され、この文字列はDate
オブジェクトとして認識され、メソッドを呼び出すことができます。[注: ユーザーによっては、 の記述の方が馴染みのある構文であると感じるかもしれません。どちらの形式でもearlier(:7days)
機能します]。オブジェクトが 7 日間戻されると、オブジェクトは-ing 化され、戻り値のダッシュ ( ) を削除するために使用されます。earlier(days => 7)
Date
Str
subst
-
https://docs.raku.org/routine/日付
https://docs.raku.org/routine/Dateish
https://raku.org