2017-03-08T19:41:26Z
からの日付のみを解析しようとしています。
望ましい出力は2017-03-08です。
POSIXシェルでT
の前の部分を抽出するには:
_time=2017-03-08T19:41:26Z
utc_date=${time%T*} # as already said
_
または、Bourne互換または非POSIXシェルの場合:
_expr "$time" : '\(.*\)T'
_
ここで、_2017-03-08T19:41:26Z
_はzulu time(UTCの別名)であり、正確な時刻を明確に指定していることに注意してください。
当時、ロンドンでは2017-03-08でしたが、バンコクでは2017-03-09(早朝)でした。
その時刻指定のlocal日付(UTC日付ではなく)を知りたい場合は、バンコクのユーザーが2017-03-09を取得し、ロンドンのユーザーが2017-03を取得します。 -08、いくつかのオプションがあります。
GNU date
:
_time=2017-03-08T19:41:26Z
date -d "$time" +%F
_
(GNUのように簡単に日付を指定すると、そのズールー形式をそのまま使用できます)
_ksh93
_と同じ:
_printf '%(%F)T\n' "$time"
_
zsh
が組み込まれている場合:
_zmodload zsh/datetime
TZ=UTC0 strftime -rs unix_time %Y-%m-%dT%TZ $time &&
strftime %Y-%m-%d $unix_time
_
(GNU ones where strftime()
/strptime()
support it)のようなシステムでは_%Y-%m-%d
_を_%F
_に置き換えることができます)。
_busybox date
_と同様:
_unix_time=$(date -u -D %Y-%m-%dT%TZ -d "$time" +%s)
date -d "@$unix_time" +%Y-%m-%d
_
cut
の使用:
カット-ファイルの各行からセクションを削除
-d、--delimiter = DELIMフィールド区切り文字にTABの代わりにDELIMを使用します
-f、--fields = LISTこれらのフィールドのみを選択します。 -sオプションが指定されていない限り、区切り文字を含まない行も出力します
echo "2017-03-08T19:41:26Z" | cut -d T -f 1
Bashでは、変数の パラメータ展開 でいくつかの演算を使用できます。
timestamp='2017-03-08T19:41:26Z'
date=${timestamp:0:10} # pick 10 characters starting at position 0
date=${timestamp%T*} # remove everything starting at the 'T'
(${variable%pattern}
は実際には標準のシェル言語の一部であり、dash
のような単純なシェルでもサポートされています。)
もちろん、これらは単純な部分文字列操作です。日付を実際にparseしたい場合は、別のことを行う必要があります。フォーマットは固定幅であるため、部分文字列の展開はもちろんここでうまく適合します。ただし、値が有効であることを確認したい場合などがあります。
Bash変数の置換でこれをカバーできます。
OLD="2017-03-08T19:41:26Z"
NEW=${OLD%T*}
echo $NEW
2017-03-08
$ {string%substring}-$ substringの最短一致を$ stringの後ろから削除します。詳細は 文字列の操作
それで、すべての数字-ダッシュ番号-ダッシュ番号を見つけますか?これは、日付の直後に "T"がなくても、より長い文字列/行で機能します。
grep -o "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]"
または同等ですが、中かっこ「repeats/multiples」を使用すると少し短くなります
grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}'
例:
$ echo 2017-03-08T19:41:26Z | grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}'
2017-03-08
入力に他のダッシュがあまりない場合は、4文字、ダッシュ、2文字、ダッシュ、さらに2文字を検索できます。
$ echo 2017-03-08T19:41:26Z | grep -o '....-..-..'
2017-03-08
GNU日付を使用できる場合、これはあなたが望むことをします:
$ d='2017-03-08T19:41:26Z'
$ date +'%F' -ud "$d"
2017-03-08
TZ
(またはロケール)の値に関する問題を回避するには、-u
オプションを使用します。
他の場所で日付値が必要な場合、ローカルTZの値はこのオプションで機能します。
$ date +'%F' -d "$d"
2017-03-08 # May change in some locales.
または、TZに特定の値を使用することを選択できます。
$ TZ=Asia/Kolkata date +'%F' -d "$d"
2017-03-09 # next day in India.
コルカタは古いカルクタの現在の名前であることに注意してください。
bash は、値が整数(秒単位)の場合にのみ実行できます。
$ printf '%(%F)T\n' $(date +'%s' -d "$d")
2017-03-08
ただし、bashはTZ
(またはロケール)の値の影響を受けます。
$ TZ=GGG+3 bash -c 'printf "%(%FT%T)T\n" $(date +"%s" -ud "$1")' sh "$d"
2017-03-08T16:41:26Z
上記のT16:に注意してください(19ではありません)。
ksh は両方の変換を実行できます(秒と形式へ):
ksh$ printf '%(%F)T\n' "$d"
2017-03-08
ただし、TZ(またはロケール)によって同様に影響を受けます。
$ TZ=GGG-7 ksh93 -c 'printf "%(%FT%T)T\n" "$1"' sh "$d"
2017-03-09T02:41:26
09T02に注意してください(08T19
ではない)
busybox 入力(-D
)のフォーマット(-d
)の説明が必要です。
$ busybox date -u -D '%Y-%m-%dT%TZ' -d "$d" +'%F'
2017-03-08
-u
を使用すると、出力に対するTZ
の影響を回避できます。ただし、busybox日付の現在のバージョンは、TimeZone値(-0400
)の解析をまだ実装していません。しかし、将来的には、-z
は将来の保護になります。
値が常に時間を示すTを持ち、常にZ
(zulu時間)である場合、この文字列操作で十分です(zuluベースの日付を取得するため)。
$ echo " ${d%%T*}"
2017-03-08
awk
で文字列を解析する別の方法:
echo 2017-03-08T19:41:26Z | awk -F"T" '{print $1}'
またはsed
を使用:
echo "2017-03-08T19:41:26Z" | sed -e "s/T.*$//g"
grep
まで'T'
echo 2017-03-08T19:41:26Z | grep -Eo "[^T]+" | head -1
原油、ただし目的固有:echo $in_date | sed 's/T.*//g'
例えば:
in_date="2017-03-08T19:41:26Z"
echo $in_date | sed 's/T.*//g'
2017-03-08
Perl
を使用して日付文字列全体を解析し、希望どおりにフォーマットします。
#!/usr/#bin/env Perl
use strict;
use warnings;
use Time::Piece;
while ( <DATA> ) {
chomp;
print Time::Piece -> strptime ( $_, "%Y-%m-%dT%H:%M:%SZ")->strftime("%Y-%m-%d");
}
__DATA__
2017-03-08T19:41:26Z
そしてワンライナーとして:
Perl -MTime::Piece -lne 'print Time::Piece->strptime($_,"%Y-%m-%dT%H:%M:%SZ")->strftime("%Y-%m-%d")'