解析日期和时间格式 - Bash
Posted
技术标签:
【中文标题】解析日期和时间格式 - Bash【英文标题】:Parsing date and time format - Bash 【发布时间】:2015-01-01 10:36:09 【问题描述】:我有这样的日期和时间格式(年月日):
20141105 11:30:00
我需要将年、月、日、小时和分钟值分配给变量。
我可以像这样年复一年地做到这一点:
year=$(awk 'print $1' log.log | sed 's/^\(....\).*/\1/')
day=$(awk 'print $1' log.log | sed 's/^.*\(..\).*/\1/')
hour=$(awk 'print $2' log.log | sed 's/^\(..\).*/\1/')
我怎样才能做到这一点?
--
我需要日志文件的每一行:
20141105 11:30:00 /bla/text.1
20141105 11:35:00 /bla/text.2
20141105 11:40:00 /bla/text.3
....
我正在尝试逐行读取此日志文件并执行以下操作:
mkdir -p "/bla/backup/$year/$month/$day/$hour/$minute"
mv $file "/bla/backup/$year/$month/$day/$hour/$minute"
这是我不工作的代码:
#!/bin/bash
LOG=/var/log/LOG
while read line
do
year=$line:0:4
month=$line:4:2
day=$line:6:2
hour=$line:9:2
minute=$line:12:2
file=$(awk 'print $3')
if [ -f "$file" ]; then
printf -v path "%s/%s/%s/%s/%s" $year $month $day $hour $minute
mkdir -p "/bla/backup/$path"
mv $file "/bla/backup/$path"
fi
done < $LOG
【问题讨论】:
你的最终目标是什么,为什么要把它们放在变量中? 我需要创建这样的路径 -> /bla/2014/11/05/11/30/ 你从哪里得到日期? Parse Date in Bash的可能重复 【参考方案1】:你根本不需要调用 awk 到日期,使用 bash 的子字符串操作
d="20141105 11:30:00"
yr=$d:0:4
mo=$d:4:2
dy=$d:6:2
hr=$d:9:2
mi=$d:12:2
printf -v dir "/bla/%s/%s/%s/%s/%s/\n" $yr $mo $dy $hr $mi
echo "$dir"
/bla/2014/11/05/11/30/
或者直接,不带所有变量。
printf -v dir "/bla/%s/%s/%s/%s/%s/\n" $d:0:4 $d:4:2 $d:6:2 $d:9:2 $d:12:2
鉴于您的日志文件:
while read -r date time file; do
d="$date $time"
printf -v dir "/bla/%s/%s/%s/%s/%s/\n" $d:0:4 $d:4:2 $d:6:2 $d:9:2 $d:12:2
mkdir -p "$dir"
mv "$file" "$dir"
done < filename
或者,假设您的文件名中没有空格或通配符:
sed -r 's#(....)(..)(..) (..):(..):.. (.*)#mv \6 /blah/\1/\2/\3/\4/\5#' | sh
【讨论】:
如何在我的日志文件的所有行中执行此操作? 编辑您的问题以显示您的日志文件示例。【参考方案2】:date
命令也可以完成这项工作
#!/bin/bash
year=$(date +'%Y' -d'20141105 11:30:00')
day=$(date +'%d' -d'20141105 11:30:00')
month=$(date +'%m' -d'20141105 11:30:00')
minutes=$(date +'%M' -d'20141105 11:30:00')
echo "$year---$day---$month---$minutes"
【讨论】:
【参考方案3】:您只能使用一个awk
month=$(awk 'print substr($1,5,2)' log.log)
year=$(awk 'print substr($1,0,4)' log.log)
minute=$(awk 'print substr($2,4,2)' log.log)
etc
【讨论】:
【参考方案4】:我猜你正在处理日志文件,它的每一行都以日期字符串开头。您可能已经编写了一个循环来处理每一行,在您的循环中,您可以这样做:
d="$(awk 'print $1,$2' <<<"$line")"
year=$(date -d"$d" +%Y)
month=$(date -d"$d" +%m)
day=$(date -d"$d" +%d)
min=$(date -d"$d" +%M)
【讨论】:
【参考方案5】:不要重复自己。
d='20141105 11:30:00'
IFS=' ' read -r year month day min < <(date -d"$d" '+%Y %d %m %M')
echo "year: $year"
echo "month: $month"
echo "day: $day"
echo "min: $min"
诀窍是让date
输出你想要的字段,用一个字符(这里是空格)分隔,把这个字符放在IFS
中,然后让read
为你做分割。像这样,您只执行一次date
,并且只生成一个子shell。
如果日期来自文件log.log
的第一行,您可以将其分配给变量d
:
IFS= read -r d < log.log
【讨论】:
【参考方案6】:eval "$(
echo '20141105 11:30:00' \
| sed 'G;s/\(....\)\(..\)\(..\) \(..\):\(..\):\(..\) *\(.\)/Year=\1\7Month=\2\7Day=\3\7Hour=\4\7Min=\5\7Sec=\6/'
)"
通过分配字符串进行评估。您可以通过将点替换为更具体的模式(例如 [0-5][0-9]
为 min 和 sec,...
posix 版本所以--posix
在 GNU sed 上
【讨论】:
【参考方案7】:我写了一个函数,我通常将它剪切并粘贴到我的脚本文件中
function getdate()
local a
a=(`date "+%Y %m %d %H %M %S" | sed -e 's/ / /'`)
year=$a[0]
month=$a[1]
day=$a[2]
hour=$a[3]
minute=$a[4]
sec=$a[5]
在脚本文件中,单独一行
获取日期
echo "year=$year,month=$month,day=$day,hour=$hour,minute=$minute,second=$sec"
当然,您可以修改我提供的内容或使用上面的答案 [6]。 该函数不接受任何参数。
【讨论】:
以上是关于解析日期和时间格式 - Bash的主要内容,如果未能解决你的问题,请参考以下文章
sh Bash - 日期模块 - 作为时间戳计数器的不同格式,函数和循环,用作父脚本的模块。
sh Bash - 日期模块 - 作为时间戳计数器的不同格式,函数和循环,用作父脚本的模块。