解析日期和时间格式 - Bash

时间:2014-11-05 09:38:21

标签: bash parsing awk sed

我有这样的日期和时间格式(yearmonthday):

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

7 个答案:

答案 0 :(得分:3)

你根本不需要调用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

答案 1 :(得分:1)

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"

答案 2 :(得分:1)

您只能使用一个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

答案 3 :(得分:1)

我猜你正在处理日志文件,每行以日期字符串开头。您可能已经编写了一个循环来处理每一行,在循环中,您可以这样做:

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)

答案 4 :(得分:1)

不要重复自己。

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

答案 5 :(得分:1)

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,...

在GNU sed上使用--posix的posix版本

答案 6 :(得分:1)

我写了一个我经常剪切并粘贴到我的脚本文件中的函数

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]}
}

在脚本文件中,在它自己的

行上

GETDATE

echo&#34; year = $ year,month = $ month,day = $ day,hour = $ hour,minute = $ minute,second = $ sec&#34;

当然,您可以修改我提供的内容或使用上面的答案[6]。 该函数不带参数。