
ファイルが変更された 2 桁の月と 2 桁の年を取得しようとしていますが、うまくいきません。
modified=$(stat -c %y "$line");
# modified="2018-08-22 14:39:36.400469308 -0400"
if [[ $modified =~ ".{2}(\d{2})-(\d{2})" ]]; then
echo ${BASH_REMATCH[0]}
echo ${BASH_REMATCH[1]
fi
- Bash デモ:http://rextester.com/DJSPH52792
- 正規表現デモ:https://regex101.com/r/UEOlMO/1
何が間違っているのでしょうか?
答え1
まず、引用符は正規表現内の特殊文字の意味を抑制します(オンラインマニュアル):
追加の二項演算子
=~
が使用可能です。... パターンの任意の部分を引用符で囲むと、引用符で囲んだ部分が文字列として一致するように強制できます。... 正規表現の文法にとって特別な文字を一致させたい場合は、その特別な意味を削除するために引用符で囲む必要があります。
マニュアルではさらに、シェルの解析と正規表現の構文の衝突を防ぐために、正規表現を変数に入れることを推奨しています。
2 番目は、\d
あなたが考えていることではなく、単にリテラル に一致するだけですd
。
また、には${BASH_REMATCH[0]}
一致する文字列全体が含まれ、インデックス1
以降にはキャプチャされたグループが含まれることに注意してください。
また、4桁の年を使用することを強くお勧めします。
modified=$(stat -c %y "$file")
re='^([0-9]{4})-([0-9]{2})'
if [[ $modified =~ $re ]]; then
echo "year: ${BASH_REMATCH[1]}"
echo "month: ${BASH_REMATCH[2]}"
else
echo "invalid timestamp"
fi
今日変更されたファイルの場合、 およびyear: 2018
となりますmonth: 08
。先頭にゼロがある数値は、シェルやその他のユーティリティによって 8 進数として扱われることに注意してください。
(1900 年代の日付を扱う必要がある場合、4 桁の年であれば問題が少なく、月日ではなく年として認識しやすくなります。)
答え2
これには正規表現は必要ありません:
$ touch -t 197001010000 myfile
$ ls -l myfile
-rw-rw-r-- 1 jackman jackman 0 Jan 1 1970 myfile
$ IFS='-' read -r year month _rest < <(stat -c %y myfile)
$ echo "$year:${year#??}"$month"
1970:70:01
答え3
代わりに、GNU を使用するとdate
、次の操作を実行できます。
eval "$(date -r "$file" +'year=%Y month=%-m day=%-d')"
変更時刻の年、月、日の要素をそれぞれ$year
、$month
およびに格納します$day
(10 進整数として、先頭のゼロが必要な場合は、およびの を削除します。2 桁の年については、も参照してください-
) 。%-m
%-d
%y
(GNU とは異なりstat
、シンボリックリンク タイプのファイルの場合、シンボリックリンク自体の変更時刻ではなく、シンボリックリンクのターゲットの変更時刻が考慮されることに注意してください。GNU ではstat
、 を使用しますstat -L
)。