我正在尝试将格式为YYYYMMDDHHMMSS的日期替换为该时间减去7小时。
该文件看起来像这样
File with text and some dates 20140716223000 20140716013000
我希望输出看起来像
File with text and some dates 20140716153000 20140715183000
我能想到的最好的是perl的替代品:
perl -ape 's/(-*\d+.\d+)/$1-70000/ge' file.txt
但显然这不是日期减法,而是简单算术。任何bash或perl语句都适用于我。也许是sed或awk声明?谢谢!
答案 0 :(得分:4)
您可以使用Time::Piece
来解析日期时间字符串并执行算术运算。它是Perl 5版本10以来的核心模块,因此不需要安装。
相关的Time::Seconds
模块以秒为单位提供各种时间间隔的有用常量。
此程序可以像您在问题中一样使用可执行替换。请注意,它不会正确处理夏令时,因为它只是从每个值中简单地减去25,200秒。
use strict;
use warnings;
use 5.010;
use Time::Piece;
use Time::Seconds qw/ ONE_HOUR /;
my $text = 'File with text and some dates 20140716223000 20140716013000';
say "Before: $text";
$text =~ s{(\d{14})}{
my $dt = Time::Piece->strptime($1, '%Y%m%d%H%M%S');
$dt -= 7 * ONE_HOUR;
$dt->strftime('%Y%m%d%H%M%S');
}ge;
say " After: $text";
<强>输出强>
Before: File with text and some dates 20140716223000 20140716013000
After: File with text and some dates 20140716153000 20140715183000
答案 1 :(得分:0)
既然你有GNU Bash,你很可能也有GNU Coreutils,所以你为什么不使用GNU date
?
$ cat file
File with text and some dates 20140716223000 20140716013000
$ cat script
#!/bin/bash
while read -a LINE; do
for i in "${!LINE[@]}"; do
[[ ${LINE[$i]} =~ ^[0-9]{14}$ ]] && {
DATE="${LINE[$i]}"
YEAR="${DATE:0:4}"
MONTH="${DATE:4:2}"
DAY="${DATE:6:2}"
HOUR="${DATE:8:2}"
MINUTE="${DATE:10:2}"
SECOND="${DATE:12:2}"
NEWDATE="$(date -d \
"-7 hours ${YEAR}-${MONTH}-${DAY}T${HOUR}:${MINUTE}:${SECOND}" \
+'%Y%m%d%H%M%S')"
LINE[$i]="$NEWDATE"
}
done
echo "${LINE[@]}"
done < "$1"
$ ./script file
File with text and some dates 20140716153000 20140715183000
答案 2 :(得分:0)
将GNU awk用于gensub()和时间函数:
$ cat tst.awk
{
head = ""
tail = $0
while ( match(tail,/\<[[:digit:]]{14}\>/) ) {
oldTime = substr(tail,RSTART,RLENGTH)
secs = mktime( gensub(/(....)(..)(..)(..)(..)(..)/,"\\1 \\2 \\3 \\4 \\5 \\6","",oldTime) )
newTime = strftime("%Y%m%d%H%M%S", secs - (7 * 60 * 60))
head = head substr(tail,1,RSTART-1) newTime
tail = substr(tail,RSTART+RLENGTH)
}
print head tail
}
$
$ awk -f tst.awk file
File with text and some dates 20140716153000 20140715183000
答案 3 :(得分:-1)
并非所有问题都应使用正则表达式。
使用Date :: Calc怎么样?它的功能正是您所需要的:
($year,$month,$day, $hour,$min,$sec) = Add_Delta_DHMS($year,$month,$day, $hour,$min,$sec, $Dd,$Dh,$Dm,$Ds);
您可以使用简单的正则表达式将日期字符串分解为年/月/日/小时/分钟/秒变量。$ Dx参数可以为负数。
在说明中,我希望当你说“减去7小时”时,你并不是想做时区数学。因为这是一个与另一个解决方案不同的问题。