![linux更改文件中的日期格式与全年](https://linux22.com/image/201397/linux%E6%9B%B4%E6%94%B9%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E6%97%A5%E6%9C%9F%E6%A0%BC%E5%BC%8F%E4%B8%8E%E5%85%A8%E5%B9%B4.png)
我正在尝试更改全年文件中的日期格式。这是我的数据。
06/30/21 07/01/21 05436841182400056721972 random text
07/06/21 07/07/21 05436841188400057034635 random text
07/17/21 07/19/21 05410191199637000037473 random text
07/21/21 07/22/21 55483821203091001733933 random text
07/24/21 07/26/21 55457021206837001077531 random text
这就是我希望数据的样子。
06/30/2021 07/01/2021 05436841182400056721972 random text
07/06/2021 07/07/2021 05436841188400057034635 random text
07/17/2021 07/19/2021 05410191199637000037473 random text
07/21/2021 07/22/2021 55483821203091001733933 random text
07/24/2021 07/26/2021 55457021206837001077531 random text
不能像我想要的那样进行大规模替换,因为 21 位于文件中的各个位置。
sed 's/21/2021/' junk_dates1
06/30/2021 07/01/21 05436841182400056721972 random text
07/06/2021 07/07/21 05436841188400057034635 random text
07/17/2021 07/19/21 05410191199637000037473 random text
07/2021/21 07/22/21 55483821203091001733933 random text
07/24/2021 07/26/21 55457021206837001077531 random text
不知道如何使用锚点技巧,因为日期后面有数据。
sed 's/21$/2021/' junk_dates1
06/30/21 07/01/21 05436841182400056721972 random text
07/06/21 07/07/21 05436841188400057034635 random text
07/17/21 07/19/21 05410191199637000037473 random text
07/21/21 07/22/21 55483821203091001733933 random text
07/24/21 07/26/21 55457021206837001077531 random text
答案1
$ sed -E -e 's=^([0-9]{2})/([0-9]{2})/([0-9]{2}) ([0-9]{2})/([0-9]{2})/([0-9]{2}) =\1/\2/20\3 \4/\5/20\6 =' input.txt
06/30/2021 07/01/2021 05436841182400056721972 random text
07/06/2021 07/07/2021 05436841188400057034635 random text
07/17/2021 07/19/2021 05410191199637000037473 random text
07/21/2021 07/22/2021 55483821203091001733933 random text
07/24/2021 07/26/2021 55457021206837001077531 random text
这适用于任何需要以 为前缀的两位数年份20
,包括21
。它使用 6 个捕获组来捕获第一个和第二个空格分隔字段的日、月和年数字。
21
顺便说一句,请注意正则表达式中 两个 s 之后的空格字符。那是您需要的“锚点”(或消歧点或识别标记或任何您想称呼的名称) - 您需要寻找的不仅仅是“21”,而是“21 和一个空格”。有点儿。这并不完全是我最终所做的(一个长匹配模式,多个捕获组锚定在行的开头,^
),但这是我开始考虑如何匹配不在末尾的 2 位数年份的地方一条线。
但请注意,虽然这解决了您的问题之一,但它使 MM/DD/YYYY 和 DD/MM/YYYY 日期格式固有的歧义问题永久化。请改用基于 ISO 8601、YYYY-MM-DD 的日期。例如:
$ sed -E -e 's=^([0-9]{2})/([0-9]{2})/([0-9]{2}) ([0-9]{2})/([0-9]{2})/([0-9]{2}) =20\3-\1-\2 20\6-\4-\5 =' input.txt
2021-06-30 2021-07-01 05436841182400056721972 random text
2021-07-06 2021-07-07 05436841188400057034635 random text
2021-07-17 2021-07-19 05410191199637000037473 random text
2021-07-21 2021-07-22 55483821203091001733933 random text
2021-07-24 2021-07-26 55457021206837001077531 random text
顺便说一句,使用 perl 正则表达式会更容易阅读,\d\d
而不是使用[0-9]{2}
:
$ perl -pe 's=^(\d\d)/(\d\d)/(\d\d) (\d\d)/(\d\d)/(\d\d) =20$3-$1-$2 20$6-$4-$5 =' input.txt
2021-06-30 2021-07-01 05436841182400056721972 random text
2021-07-06 2021-07-07 05436841188400057034635 random text
2021-07-17 2021-07-19 05410191199637000037473 random text
2021-07-21 2021-07-22 55483821203091001733933 random text
2021-07-24 2021-07-26 55457021206837001077531 random text
不幸的是,没有多少版本能够sed
理解 perl 的\d
.我唯一知道的是超级sed它有一个-R
选项告诉它使用 perl 正则表达式语法:
ssed -R 's=^(\d\d)/(\d\d)/(\d\d) (\d\d)/(\d\d)/(\d\d) =20\3-\1-\2 20\6-\4-\5 =' input.txt
如果您在 Debian 上运行,它就在ssed
软件包中。它也可以打包用于其他发行版。无论哪种方式,与仅使用perl -p
or相比并没有真正的任何好处perl -n
。
答案2
我建议这个
$ sed 's;\(../../\)21;\12021;g' foo.txt
06/30/2021 07/01/2021 05436841182400056721972 random text
07/06/2021 07/07/2021 05436841188400057034635 random text
07/17/2021 07/19/2021 05410191199637000037473 random text
07/21/2021 07/22/2021 55483821203091001733933 random text
07/24/2021 07/26/2021 55457021206837001077531 ransom text
\(../../\)21
斜杠括号\(...\)
捕获模式char char slash char char slash
,该模式在替换 by 中被引用\1
。模式 is 之后21
,被 替换2021
。
有了选项-E
(--regexp-extended
)就更清楚了:$ sed 's;(../../)21;\12021;g'
。
答案3
假设要插入的字符位置(15 和 6)20
始终相同:
sed 's/.\{15\}/&20/;s/.\{6\}/&20/' file
06/30/2021 07/01/2021 05436841182400056721972 random text
07/06/2021 07/07/2021 05436841188400057034635 random text
07/17/2021 07/19/2021 05410191199637000037473 random text
07/21/2021 07/22/2021 55483821203091001733933 random text
07/24/2021 07/26/2021 55457021206837001077531 random text
答案4
$ sed 's:/\(.. \):/20\1:g' file
06/30/2021 07/01/2021 05436841182400056721972 random text
07/06/2021 07/07/2021 05436841188400057034635 random text
07/17/2021 07/19/2021 05410191199637000037473 random text
07/21/2021 07/22/2021 55483821203091001733933 random text
07/24/2021 07/26/2021 55457021206837001077531 random text
您确实应该考虑将日期格式更改为 YYYY/MM/DD 或类似格式,因为它更容易使用,例如您可以将该格式的日期作为字符串进行排序和比较:
$ sed 's:\(.....\)/\(..\) :20\2/\1 :g' file
2021/06/30 2021/07/01 05436841182400056721972 random text
2021/07/06 2021/07/07 05436841188400057034635 random text
2021/07/17 2021/07/19 05410191199637000037473 random text
2021/07/21 2021/07/22 55483821203091001733933 random text
2021/07/24 2021/07/26 55457021206837001077531 random text
或 ISO 8601 标准:
$ sed 's:\(..\)/\(..\)/\(..\):20\3-\1-\2:g' file
2021-06-30 2021-07-01 05436841182400056721972 random text
2021-07-06 2021-07-07 05436841188400057034635 random text
2021-07-17 2021-07-19 05410191199637000037473 random text
2021-07-21 2021-07-22 55483821203091001733933 random text
2021-07-24 2021-07-26 55457021206837001077531 random text