解析日期和时间格式 - Bash

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26753757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:42:47  来源:igfitidea点击:

Parsing date and time format - Bash

bashparsingawksed

提问by onur

I have date and time format like this(yearmonthday):

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

20141105 11:30:00

I need assignment year, month, day, hour and minute values to variable.

我需要将年、月、日、小时和分钟值分配给变量。

I can do it year, day and hour like this:

我可以像这样在年、日和小时内做到这一点:

year=$(awk '{print }' log.log | sed 's/^\(....\).*//')
day=$(awk '{print }' log.log | sed 's/^.*\(..\).*//')  
hour=$(awk '{print }' log.log | sed 's/^\(..\).*//')  

How can I do this for month and minute?

我怎样才能在一个月和一分钟内做到这一点?

--

——

And I need that every line of my log file:

我需要我的日志文件的每一行:

20141105 11:30:00 /bla/text.1
20141105 11:35:00 /bla/text.2
20141105 11:40:00 /bla/text.3
.... 

I'm trying read line by line this log file and do this:

我正在尝试逐行读取此日志文件并执行以下操作:

mkdir -p "/bla/backup/$year/$month/$day/$hour/$minute"
mv $file "/bla/backup/$year/$month/$day/$hour/$minute"

Here is my not working code:

这是我不工作的代码:

#!/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 }')

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

采纳答案by glenn Hymanman

You don't need to call out to awk to date at all, use bash's substring operations

你根本不需要调用 awk 到 date,使用 bash 的 substring 操作

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/

Or directly, without all the variables.

或者直接,没有所有的变量。

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}


Given your log file:

鉴于您的日志文件:

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

or, making a big assumption that there are no whitespace or globbing characters in your filenames:

或者,假设文件名中没有空格或通配符:

sed -r 's#(....)(..)(..) (..):(..):.. (.*)#mv  /blah/////#' | sh

回答by NeronLeVelu

eval "$( 
   echo '20141105 11:30:00' \
    | sed 'G;s/\(....\)\(..\)\(..\) \(..\):\(..\):\(..\) *\(.\)/Year=Month=Day=Hour=Min=Sec=/'
    )"

pass via a assignation string to evaluate. You could easily adapt to also check the content by replacing dot per more specific pattern like [0-5][0-9]for min and sec, ...

通过分配字符串进行评估。您可以轻松地通过替换每个更具体的模式(例如[0-5][0-9]分钟和秒)的点来检查内容,...

posix version so --posixon GNU sed

posix 版本--posix等 GNU sed

回答by Leslie Satenstein

I wrote a function that I usually cut and paste into my script files

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

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

in the script file, on a line of it's own

在脚本文件中,在它自己的一行上

getdate

获取日期

echo "year=$year,month=$month,day=$day,hour=$hour,minute=$minute,second=$sec"

echo "year=$year,month=$month,day=$day,hour=$hour,minute=$minute,second=$sec"

Of course, you can modify what I provided or use answer [6] above. The function takes no arguments.

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

回答by Kalanidhi

datecommand also do this work

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"

回答by Jotne

You can use only one awk

您只能使用一个 awk

month=$(awk '{print substr(,5,2)}' log.log)
year=$(awk '{print substr(,0,4)}' log.log)
minute=$(awk '{print substr(,4,2)}' log.log)
etc

回答by Kent

I guess you are processing the log file, which each line starts with the date string. You may have already written a loop to handle each line, in your loop, you could do:

我猜您正在处理日志文件,其中每一行都以日期字符串开头。您可能已经编写了一个循环来处理每一行,在您的循环中,您可以执行以下操作:

d="$(awk '{print ,}' <<<"$line")"
year=$(date -d"$d" +%Y)
month=$(date -d"$d" +%m)
day=$(date -d"$d" +%d)
min=$(date -d"$d" +%M)

回答by gniourf_gniourf

Don't repeat yourself.

不要重复自己。

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"

The trick is to ask dateto output the fields you want, separated by a character (here a space), to put this character in IFSand ask readto do the splitting for you. Like so, you're only executing dateonce and only spawn one subshell.

诀窍是要求date输出您想要的字段,由一个字符(这里是一个空格)分隔,将这个字符放入IFS并要求read为您进行拆分。像这样,您只执行date一次并且只生成一个子shell。

If the date comes from the first line of the file log.log, here's how you can assign it to the variable d:

如果日期来自文件的第一行,以下是log.log将其分配给变量的方法d

IFS= read -r d < log.log