通过“sed”命令就地修改日期格式

通过“sed”命令就地修改日期格式

我正在尝试修改文本中存在 as2016-Dec-24或 的日期2016-12-24,并且我必须将它们替换为24/12/2016.

我可以用什么方法sed -i来做到这一点吗?

输入示例:

节日或纪念日 宗教团体日期 附加说明 *Rosh Hashanah(新年) 犹太教 2014 年 9 月 25 日 - 2014 年 9 月 26 日 指定观察员非工作日 Navaratri/Dassehra 印度教 9 月 2014 年 10 月 3 日

*Yom Kippur(赎罪日)犹太人 2014 年 10 月 4 日,指定观察员非工作日

赞助会议 名称 地点 会议日期 2017 IEEE 传感器应用研讨会 (SAS) 美国 2017-03-13, 2017-03-14, 2017-03-15 2017 IEEE 国际医疗测量和应用研讨会 (MeMeA) 美国 2017-05 -07至2017-05-10 2017年IEEE国际仪器仪表与测量技术会议(I

这就是我到目前为止所尝试过的。

sed -i -e 's/\([0-9]\{4\}\)-\(01|Jan\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(02|Feb\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(03|Mar\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(04|Apr\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(05|May\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(06|Jun\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(07|Jul\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(08|Aug\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(09|Sep\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(10|Oct\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(11|Nov\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(12|Dec\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1

答案1

如果您有权访问 GNU date(Linux 系统上的默认设置),您可以执行以下操作:

$ sed -E 's/(.*)-([a-z]+)(.+)/\2\3-\1/i' file | 
    while read d; do date -d "$d" +%d/%m/%y; done
24/12/16
24/12/16

这会将行更改为2016-Dec-24Dec-24-2016GNU 可以理解的格式date),保留行2016-12-24(GNU 日期已经理解的格式),然后将每一行作为输入日期字符串传递给date.它不会就地执行此操作,也不会使用sed -i但几乎可以肯定是最简单的方法。

如果你真的需要使用 来执行此操作sed,您可以列出所有月份和相应的数字:

$ for m in {1..12}; do printf '%s %s\n' "$m" $(date -d "$m/1/2016" +%b); done
1 Jan
2 Feb
3 Mar
4 Apr
5 May
6 Jun
7 Jul
8 Aug
9 Sep
10 Oct
11 Nov
12 Dec

将其另存为months,然后迭代它以修改您的文件:

while read num mon; do 
    sed -Ei "s/$mon/$num/; s#(.*)-(.*)-(.*)#\3/\2/\1#" file
done < months 

或者,如果您的 sed 实现需要单独-e

while read num mon; do 
    sed -i -e "s/$mon/$num/" -Ee 's#(.*)-(.*)-(.*)#\3/\2/\1#' file
done < months 

第一个替换将用相应的数字替换所有字母月份名称,第二个替换将移动内容以获得您想要的格式。

答案2

我在正则表达式方面看到的唯一错误是,在基本(BRE)模式下,|是文字 - 你需要\|将其设为逻辑“或”,\(01\|Jan\)等等。

如果您的版本支持,-e那么我看不出有任何充分的理由进行多次调用- 您只需在一次调用中sed链接即可。-e <expr1> -e <expr2> ...所以

sed -i \
  -e 's/\([0-9]\{4\}\)-\(01\|Jan\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(02\|Feb\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(03\|Mar\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(04\|Apr\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(05\|May\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(06\|Jun\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(07\|Jul\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(08\|Aug\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(09\|Sep\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(10\|Oct\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(11\|Nov\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(12\|Dec\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1

然而,还有更优雅的方法可以做到这一点 - 例如在 perl usingstrptime和函数中(例如strftime由模块提供):Time::Piece

perl -i -MTime::Piece -pe '
  s|\d{4}-\d\d-\d\d?|Time::Piece->strptime($&, "%Y-%m-%d")->strftime("%Y/%m/%d")|ge;
  s|\d{4}-...-\d\d?|Time::Piece->strptime($&, "%Y-%b-%d")->strftime("%Y/%m/%d")|ge;
' file

答案3

sed -r -i '
/([0-9]{4})-([[:alpha:]]{3})-([0-9]{2})/ {
    s#([0-9]{4})-Jan-([0-9]{2})#\2/01/\1#g
    s#([0-9]{4})-Feb-([0-9]{2})#\2/02/\1#g
    s#([0-9]{4})-Mar-([0-9]{2})#\2/03/\1#g
    s#([0-9]{4})-Apr-([0-9]{2})#\2/04/\1#g
    s#([0-9]{4})-May-([0-9]{2})#\2/05/\1#g
    s#([0-9]{4})-Jun-([0-9]{2})#\2/06/\1#g
    s#([0-9]{4})-Jul-([0-9]{2})#\2/07/\1#g
    s#([0-9]{4})-Aug-([0-9]{2})#\2/08/\1#g
    s#([0-9]{4})-Sep-([0-9]{2})#\2/09/\1#g
    s#([0-9]{4})-Oct-([0-9]{2})#\2/10/\1#g
    s#([0-9]{4})-Nov-([0-9]{2})#\2/11/\1#g
    s#([0-9]{4})-Dec-([0-9]{2})#\2/12/\1#g
}
s#([0-9]{4})-([0-9]{2})-([0-9]{2})#\3/\2/\1#g
' file

相关内容