最初の列にUnixタイムスタンプが含まれているawk/grepを含むテキストファイルを表示したいと思います。表示中に人間が読める時間に変換するにはどうすればよいですか?
行がUNIXタイムスタンプで始まる場合は、次のようにする必要があります。
Perl -pe 's/^(\d+)/localtime $1/e' inputfilename
Perl -p
は、入力の各行に対して実行される-e
で渡された式に対してループを呼び出し、ループの最後にバッファを出力します。
この式では、置換コマンドs///
を使用して、各行の先頭で一連の数字を照合およびキャプチャし、UNIXタイムスタンプとして解釈されるこれらの数字のローカル時間表現に置き換えます。 /e
は、置換パターンが式として評価されることを示します。
AWKが Gawk の場合、strftime
を使用できます。
gawk '{ print strftime("%c", $1) }'
最初の列のタイムスタンプを現在のロケールのデフォルトの日付/時刻表現に変換します。
これを使用して、コンテンツを表示する前に変換できます。
gawk '{ print gensub($1, strftime("%c", $1), 1) }' inputfile
ダンが彼の答えで言及している のように、Gnu date(1)
コマンドには、出力される日付として扱う日付またはタイムスタンプを含む_-d
_パラメーターを指定できます。 (ただし、これはPOSIXまたはBSDのdate(1)
コマンドでは使用できません。)_@1571806800
_は、_time_t
_整数を指定するために使用される形式です。
フィルターとして機能するBashシェル関数を次に示します。入力から行を読み取り、すべての数字が行で始まるWordがタイムスタンプであると想定し、それを私の好きな形式の1つで人間が読める出力に変換します。
_ts2hr() {
while read n rest; do
if [[ $n =~ ^[0-9][0-9]*$ ]]; then
echo "$(date -d @"$n" +"%Y-%m-%d %T")" "$rest"
else
echo "$n" "$rest"
fi
done
}
_
入力と出力は次のようになります。
_ts2hr <<____
1571806123 first line
# A comment?
1571720456 second date's here
Just a regular sentence.
1571547789 The last line.
____
2019-10-23 13:48:43 first line
# A comment?
2019-10-22 14:00:56 second date's here
Just a regular sentence.
2019-10-20 14:03:09 The last line.
_
必要に応じて関数を微調整して、必要な特定の入力および出力フォーマット、および使用可能なツールを処理できます。上記の関数がBashであるのは、主に_=~
_演算子によってパターンマッチングが容易になったためです。 Bourne Shellでこれが必要な場合は、チェックを別の方法でコーディングする必要があります。
「日付」を使用
これには、Perl、awk、php、または長い算術式は必要ありません。 gnu "date"を使用してこれを行うことができます。これは、この種のことには本当に非常に役立ちます。 「日付」の他のバージョンの場合、YMMV。
$ date -d '1/1/1970 GMT 1571889039 seconds'
Wed Oct 23 20:50:39 PDT 2019
ここで起こっているのは、時間とその調整を指定しているということです。時間は、1970年1月1日、グリニッジ標準時、Unix Epochです。 (真夜中は明示的に指定されていません。時刻を省略した場合は常に暗黙的に使用されます。)
時間に1571889039秒の調整が追加されます。代わりに、タイムスタンプを使用してください。ドキュメントでは、この機能に「相対」という単語を使用しています。
より簡潔なバージョンがあり、マンページの例によってのみドキュメント化されています。これは、新しいバージョンのgnu dateで機能します。
$ date -d @2147483647
Mon Jan 18 19:14:07 PST 2038
日付を頻繁に操作する必要がある場合は、日付コマンドについて理解してください。それは単なる時計ではありません。シェルの日付/時刻ライブラリです。
これのポータブルバージョンでは、最悪の場合、自分で計算を実行できます。 Unixタイムスタンプは POSIX XBD 4.16秒からのエポック で定義されています:
tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 + (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 - ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
これはあなたが望むマッピングの逆なので、少しの作業* それを逆にするために必要です。これにより、「POSIX UTC」の詳細が表示されますが、現在のタイムゾーンでフォーマットする方法が必要になる場合があります。現れる date -d
は移植性がないため、これを行うための適切な方法があるかどうかは不明です。
* Okそれは控えめな表現かもしれません。
GNUの日付がない場合、またはstrftimeまたは同等のプログラミング言語にアクセスできない場合は、自分で計算を行う必要があります。これは、コードゴルフの領域に入ります。
unix_to_iso_utc () {
local day_unix=$(($1 / 86400))
local day_offset=$(($1 % 86400))
local d=$(($day_unix + 719468))
local y=$((($d - ($d+2+3*$d/146097)/1461 + ($d-$d/146097)/36524 - ($d+1)/146097)/365))
local y_d=$((365*$y + $y/4 - $y/100 + $y/400))
local y_offset=$(($d - $y_d))
local m=$((($y_offset - ($y_offset+20)/50) / 30))
local m_d=$((30*$m + 3*($m+4)/5 - 2))
local day=$(($y_offset - $m_d + 1))
local m_cont=$((12*$y + $m + 2))
local year=$(($m_cont/12))
local month=$(($m_cont%12 + 1))
local hour=$(($day_offset / 3600))
local hour_offset=$(($day_offset % 3600))
local minute=$(($hour_offset / 60))
local second=$(($hour_offset % 60))
DATE=$(printf "%04d-%02d-%02dT%02d:%02d:%02d" $year $month $day $hour $minute $second)
}
また、必要なものをハードコーディングできない限り、その時点ではおそらくタイムゾーンデータベースがないため、これは大きな実用上の問題になる可能性があります。
すでに述べたように、シェルやAWKを使用してこれを行うポータブルな方法は実際にはありません。 GAWKはそれを実行できますが、GAWK strftime
はAWKの特定のバージョン、つまりMAWKでは利用できません。また、MAWKは人気のあるディストリビューション(Debianなど)でも使用されます。
これには、ポータブルシェルまたはAWKソリューションが利用可能であることに同意します。しかし、そうではなく、おそらくおそらく何年もの間、そうなることはないでしょうが、最善の解決策は、プログラミング言語を使用することです。 Perlが提案されています。別のオプションはPHPです。
$ cat input.txt
1571806800 blue
1571720400 green
1571634000 orange
1571547600 red
1571461200 yellow
$ cat app.php
<?php
$r1 = fopen('input.txt', 'r');
while (true) {
$s1 = fgets($r1);
if ($s1 === false) {
break;
}
$a1 = explode(' ', $s1);
$n1 = + $a1[0];
echo date(DATE_W3C, $n1), "\n";
}
$ php app.php
2019-10-23T05:00:00+00:00
2019-10-22T05:00:00+00:00
2019-10-21T05:00:00+00:00
2019-10-20T05:00:00+00:00
2019-10-19T05:00:00+00:00