在 Shell 中转换日期

发布于 2024-12-22 07:14:34 字数 182 浏览 1 评论 0原文

如何在 shellscript 中将一种日期格式转换为另一种格式?

示例:

旧格式是

MM-DD-YY HH:MM

,但我想将其转换为

YYYYMMDD.HHMM

How can I convert one date format to another format in a shellscript?

Example:

the old format is

MM-DD-YY HH:MM

but I want to convert it into

YYYYMMDD.HHMM

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

以歌曲疗慰 2024-12-29 07:14:34

就像“20${D:6:2}${D:0:2}${D:3:2}.${D:9:2}${D:12:2}00”< /code>,如果 $D 变量中是旧日期。

Like "20${D:6:2}${D:0:2}${D:3:2}.${D:9:2}${D:12:2}00", if the old date in the $D variable.

森罗 2024-12-29 07:14:34

利用 shell 的分词和位置参数:

date="12-31-11 23:59"
IFS=" -:"
set -- $date
echo "20$3$1$2.$4$5"  #=> 20111231.2359

Take advantage of the shell's word splitting and the positional parameters:

date="12-31-11 23:59"
IFS=" -:"
set -- $date
echo "20$3$1$2.$4$5"  #=> 20111231.2359
你的背包 2024-12-29 07:14:34
 myDate="21-12-11 23:59"
 #fmt is DD-MM-YY HH:MM
 outDate="20${myDate:6:2}${myDate:3:2}${myDate:0:2}.${myDate:9:2}${myDate:12:2}00"

 case "${outDate}" in 
    2[0-9][0-9][0-9][0-1][0-9][0-3][0-9].[0-2][0-9][0-5][[0-9][0-5][[0-9] ) 
      : nothing_date_in_correct_format 
    ;; 
    * ) echo bad format for ${outDate} >&2
    ;; 
 esac

请注意,如果您有一个大文件要处理,那么上述过程是一个昂贵的过程。对于基于文件的数据,我建议类似

 cat infile
 ....|....|21-12-11 23:59|22-12-11 00:01| ...|

 awk '
    function reformatDate(inDate) {
       if (inDate !~ /[0-3][0-9]-[0-1][0-9]-[0-9][0-9] [0-2][0-9]:[0-5][[0-9]/) {
         print "bad date format found in inDate= "inDate
         return -1
       }
       # in format assumed to be DD-MM-YY HH:MM(:SS)
       return (2000 + substr(inDate,7,2) ) substr(inDate,4,2) substr(inDate, 1,2) \
              "." substr(inDate,10,2) substr(inDate,13,2) \
               ( substr(inDate,16,2) ?  substr(inDate,16,2) : "00" )
    }
    BEGIN {       
       #add or comment out for each column of data that is a date value to convert
       # below is for example, edit as needed.
       dateCols[3]=3
       dateCols[4]=4
       # for awk people, I call this the pragmatic use of associative arrays ;-)

       #assuming pipe-delimited data for columns
       #....|....|21-12-11 23:59|22-12-11 00:01| ...|
       FS=OFS="|"
    }
    # main loop for each record
    {
       for (i=1; i<=NF; i++) {
         if (i in dateCols) {
            #dbg print "i=" i "\t$i=" $i
            $i=reformatDate($i)
         }
       }
       print $0
    }' infile

output

....|....|20111221.235900|20111222.000100| ...|

我希望这有帮助。

 myDate="21-12-11 23:59"
 #fmt is DD-MM-YY HH:MM
 outDate="20${myDate:6:2}${myDate:3:2}${myDate:0:2}.${myDate:9:2}${myDate:12:2}00"

 case "${outDate}" in 
    2[0-9][0-9][0-9][0-1][0-9][0-3][0-9].[0-2][0-9][0-5][[0-9][0-5][[0-9] ) 
      : nothing_date_in_correct_format 
    ;; 
    * ) echo bad format for ${outDate} >&2
    ;; 
 esac

Note that if you have a large file to process, then the above is an expensive(ish) process. For filebased data I would recommend something like

 cat infile
 ....|....|21-12-11 23:59|22-12-11 00:01| ...|

 awk '
    function reformatDate(inDate) {
       if (inDate !~ /[0-3][0-9]-[0-1][0-9]-[0-9][0-9] [0-2][0-9]:[0-5][[0-9]/) {
         print "bad date format found in inDate= "inDate
         return -1
       }
       # in format assumed to be DD-MM-YY HH:MM(:SS)
       return (2000 + substr(inDate,7,2) ) substr(inDate,4,2) substr(inDate, 1,2) \
              "." substr(inDate,10,2) substr(inDate,13,2) \
               ( substr(inDate,16,2) ?  substr(inDate,16,2) : "00" )
    }
    BEGIN {       
       #add or comment out for each column of data that is a date value to convert
       # below is for example, edit as needed.
       dateCols[3]=3
       dateCols[4]=4
       # for awk people, I call this the pragmatic use of associative arrays ;-)

       #assuming pipe-delimited data for columns
       #....|....|21-12-11 23:59|22-12-11 00:01| ...|
       FS=OFS="|"
    }
    # main loop for each record
    {
       for (i=1; i<=NF; i++) {
         if (i in dateCols) {
            #dbg print "i=" i "\t$i=" $i
            $i=reformatDate($i)
         }
       }
       print $0
    }' infile

output

....|....|20111221.235900|20111222.000100| ...|

I hope this helps.

俏︾媚 2024-12-29 07:14:34

已经有一个很好的答案了,但是你说你想要在评论中找到替代方案,所以这是我的[相比之下相当糟糕]方法:

read sourcedate < <(echo "12-13-99 23:59");
read sourceyear < <(echo $sourcedate | cut -c 7-8);
if [[ $sourceyear < 50 ]]; then
read fullsourceyear < <(echo -n 20; echo $sourceyear);
else
read fullsourceyear < <(echo -n 19; echo $sourceyear);
fi;
read newsourcedate < <(echo -n $fullsourceyear; echo -n "-"; echo -n $sourcedate | cut -c -5);
read newsourcedate < <(echo -n $newsourcedate; echo -n $sourcedate | cut -c 9-14);
read newsourcedate < <(echo -n $newsourcedate; echo :00);
date --date="$newsourcedate" +%Y%m%d.%H%M%S

所以,第一行只读取一个日期,然后我们得到两位数的年份,然后我们根据它是否小于 50 将其附加到 '20''19' (因此这将为您提供从 1950 年到 2049 年的年份 - 请随意切换线)。然后我们附加一个连字符以及月份和日期。然后我们附加一个空格和时间,最后我们附加 ':00' 作为秒(再次随意设置您自己的默认值)。最后,我们使用 GNU 日期来读取它(因为它现在已经标准化)并以不同的格式打印它(您可以编辑)。

它比切割字符串更长、更难看,但在最后一行保留格式可能是值得的。您也可以使用您在第一个答案中刚刚学到的速记法来大大缩短它。

祝你好运。

There is a good answer down already, but you said you wanted an alternative in the comments, so here is my [rather awful in comparison] method:

read sourcedate < <(echo "12-13-99 23:59");
read sourceyear < <(echo $sourcedate | cut -c 7-8);
if [[ $sourceyear < 50 ]]; then
read fullsourceyear < <(echo -n 20; echo $sourceyear);
else
read fullsourceyear < <(echo -n 19; echo $sourceyear);
fi;
read newsourcedate < <(echo -n $fullsourceyear; echo -n "-"; echo -n $sourcedate | cut -c -5);
read newsourcedate < <(echo -n $newsourcedate; echo -n $sourcedate | cut -c 9-14);
read newsourcedate < <(echo -n $newsourcedate; echo :00);
date --date="$newsourcedate" +%Y%m%d.%H%M%S

So, the first line just reads a date in, then we get the two-digit year, then we append it to '20' or '19' based on if it's less than 50 (so this would give you years from 1950 to 2049 - feel free to shift the line). Then we append a hyphen and the month and date. Then we append a space and the time, and lastly we append ':00' as the seconds (again feel free to make your own default). Lastly we use GNU date to read it in (since it's been standardized now) and print it in a different format (which you can edit).

It's a lot longer and uglier than cutting up the string, but having the format in the last line may be worth it. Also you could shorten it significantly with the shorthand you just learned in the first answer.

Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文