从 shell 脚本中的字符串中提取日期字段的更可靠方法
More robust way of extracting date field from string in shell script
我有一个描述我帐户的活动目录到期日期的字符串。我想 use/parse 这个字符串并在到期日期即将到来时做一些事情。现在我在提取完整字符串的日期部分时遇到问题。字符串是:
Password expires 1-4-2015 15:41:05
我想从中提取 1-4-2014
,但是当日期为 20-12-2015
时,该机制应该也可以工作。不幸的是,我无法配置源系统以使其输出前导零。我已经尝试将字符串传送到 cut -c30-39
,但显然这不适用于总长度较长的字符串(如 20-12-2015
)。
所以我正在寻找更强大的解决方案,比如提取直到第二个 -
字符后的最后 4 位数字。
你可以使用 grep,
$ echo 'Password expires 1-4-2015 15:41:05' | grep -o '\b[0-9]\{1,2\}-[0-9]\{1,2\}-[0-9]\{4\}\b'
1-4-2015
$ echo 'Password expires 20-12-2015 15:41:05' | grep -o '\b[0-9]\{1,2\}-[0-9]\{1,2\}-[0-9]\{4\}\b'
20-12-2015
只查询年份。
$ echo 'Password expires 20-12-2015 15:41:05' | grep -oP '^(?:[^-]*-){2}\K\d{4}\b'
2015
只得到一天
$ echo 'Password expires 1-4-2015 15:41:05' | grep -oP '\b[0-9]{1,2}(?=-[0-9]{1,2}-[0-9]{4}\b)'
1
只获取月份
$ echo 'Password expires 1-4-2015 15:41:05' | grep -oP '\b[0-9]{1,2}-\K[0-9]{1,2}(?=-[0-9]{4}\b)'
4
或者:
awk "{print }"
或
tr -s ' ' | cut -d ' ' -f 3
这是假设您在 "third thing" 之后。然后用date
解析,验证。不幸的是,因为它不明确,所以您的日期字符串不会被解析。
您需要将其反转 - date
的某些版本具有 -f
输入格式说明符,但并非全部。 (我很确定如果你使用 Perl,Time::Piece 和 strptime,你也可以这样做,但怀疑这超出了范围)
date -d "2015-1-4 15:41:05" +"%s"
#1420386065
然后您可以将其与 date +"%s"
进行数字比较,以检查它的到来时间。您可以使用 cut
或 awk
来提取日期字段。
NEWDATE=`echo $MYDATE | awk -F- '{print "-""-"}'`
date -d "$NEWDATE $TIME" +"%s"
串在一起可能会变成这样:
STRING="Password expires 1-4-2015 15:41:05"
DATE=`echo $STRING | awk '{print }'`
TIME=`echo $STRING | awk '{print }'`
NEWDATE=`echo $DATE | awk -F- '{print "-""-"}'`
EPOCH_EXP=`date -d "$NEWDATE $TIME" +"%s"`
EPOCH_TIME=`date +"%s"`
EXPIRES_S=$(($EPOCH_TIME - $EPOCH_EXP))
echo "Password expires in $EXPIRES_S seconds"
(我相信这可以做得更好,但这主要是为了说明)
两个样本没有正则表达式:
$ echo "Password expires 1-4-2015 15:41:05" | tr -s " " | cut -d' ' -f3
1-4-2015
$ echo "Password expires 20-4-2015 15:41:05" | tr -s " " | cut -d' ' -f3
20-4-2015
我有一个描述我帐户的活动目录到期日期的字符串。我想 use/parse 这个字符串并在到期日期即将到来时做一些事情。现在我在提取完整字符串的日期部分时遇到问题。字符串是:
Password expires 1-4-2015 15:41:05
我想从中提取 1-4-2014
,但是当日期为 20-12-2015
时,该机制应该也可以工作。不幸的是,我无法配置源系统以使其输出前导零。我已经尝试将字符串传送到 cut -c30-39
,但显然这不适用于总长度较长的字符串(如 20-12-2015
)。
所以我正在寻找更强大的解决方案,比如提取直到第二个 -
字符后的最后 4 位数字。
你可以使用 grep,
$ echo 'Password expires 1-4-2015 15:41:05' | grep -o '\b[0-9]\{1,2\}-[0-9]\{1,2\}-[0-9]\{4\}\b'
1-4-2015
$ echo 'Password expires 20-12-2015 15:41:05' | grep -o '\b[0-9]\{1,2\}-[0-9]\{1,2\}-[0-9]\{4\}\b'
20-12-2015
只查询年份。
$ echo 'Password expires 20-12-2015 15:41:05' | grep -oP '^(?:[^-]*-){2}\K\d{4}\b'
2015
只得到一天
$ echo 'Password expires 1-4-2015 15:41:05' | grep -oP '\b[0-9]{1,2}(?=-[0-9]{1,2}-[0-9]{4}\b)'
1
只获取月份
$ echo 'Password expires 1-4-2015 15:41:05' | grep -oP '\b[0-9]{1,2}-\K[0-9]{1,2}(?=-[0-9]{4}\b)'
4
或者:
awk "{print }"
或
tr -s ' ' | cut -d ' ' -f 3
这是假设您在 "third thing" 之后。然后用date
解析,验证。不幸的是,因为它不明确,所以您的日期字符串不会被解析。
您需要将其反转 - date
的某些版本具有 -f
输入格式说明符,但并非全部。 (我很确定如果你使用 Perl,Time::Piece 和 strptime,你也可以这样做,但怀疑这超出了范围)
date -d "2015-1-4 15:41:05" +"%s"
#1420386065
然后您可以将其与 date +"%s"
进行数字比较,以检查它的到来时间。您可以使用 cut
或 awk
来提取日期字段。
NEWDATE=`echo $MYDATE | awk -F- '{print "-""-"}'`
date -d "$NEWDATE $TIME" +"%s"
串在一起可能会变成这样:
STRING="Password expires 1-4-2015 15:41:05"
DATE=`echo $STRING | awk '{print }'`
TIME=`echo $STRING | awk '{print }'`
NEWDATE=`echo $DATE | awk -F- '{print "-""-"}'`
EPOCH_EXP=`date -d "$NEWDATE $TIME" +"%s"`
EPOCH_TIME=`date +"%s"`
EXPIRES_S=$(($EPOCH_TIME - $EPOCH_EXP))
echo "Password expires in $EXPIRES_S seconds"
(我相信这可以做得更好,但这主要是为了说明)
两个样本没有正则表达式:
$ echo "Password expires 1-4-2015 15:41:05" | tr -s " " | cut -d' ' -f3
1-4-2015
$ echo "Password expires 20-4-2015 15:41:05" | tr -s " " | cut -d' ' -f3
20-4-2015