更改同一文件夹中许多文本文件(*.txt)中间具有日期时间戳的 XML 字符串的格式

更改同一文件夹中许多文本文件(*.txt)中间具有日期时间戳的 XML 字符串的格式

我有很多带有 XML 格式的日期的文本文件,格式如下:

<DATA2020-04-13T08:59:05.427 />

需要改成这样:

<DATA>2020-04-13T08:59:05.427</DATA>

笔记:

日期和时间因字符串而异,并且不能更改。每行中该字符串之前和之后都有更多 XML 格式的内容。另外,使用 Unixdate也不是一个选择,我确实需要更改文件内的 XML 字符串。

我正在考虑使用sed//查找和替换awkperl也许使用通配符。谁能想出一种方法来实现这一目标吗?

答案1

$ echo '<DATA2020-04-13T08:59:05.427 />' | sed -E 's/<DATA(20[^/]*) \/>/<DATA>\1<\/DATA>/'
<DATA>2020-04-13T08:59:05.427</DATA>

或者,使用=代替 作为分隔符/,以避免必须反斜杠转义 s /

$ echo '<DATA2020-04-13T08:59:05.427 />' | sed -E 's=<DATA(202[^/]*) />=<DATA>\1</DATA>='
<DATA>2020-04-13T08:59:05.427</DATA>

这使得它更容易阅读(当然,您现在必须转义=搜索模式和替换文本中的任何字符)。


您也可以在 perl 中使用几乎相同的正则表达式(主要区别在于,虽然\1在 perl 中工作以引用捕获组,但使用 更好且更正确$1),它有更多用于分隔s运算符的选项,例如匹配对{}

$ echo '<DATA2020-04-13T08:59:05.427 />' |
    perl -pe 's{<DATA(202[^/]*) />}                  
               {<DATA>$1</DATA>}'
<DATA>2020-04-13T08:59:05.427</DATA>

perl 还有一个/x修饰符来忽略未使用括号表达式转义或未\在括号表达式中转义的空格(包括换行符)。它也忽略#评论。目的是让您能够更轻松地在代码中编写更具可读性、记录在案的正则表达式。

man perlre有关 perl 正则表达式的详细信息,请参阅参考资料。

答案2

使用支持 ERE 的 sed -E(例如 GNU 或 BSD sed):

$ sed -E 's:<(DATA)([^ ]+) />:<\1>\2</\1>:' file
<DATA>2020-04-13T08:59:05.427</DATA>

否则,在每个 Unix 机器上的任何 shell 中使用任何 sed:

$ sed 's:<\(DATA\)\([^ ]*\) />:<\1>\2</\1>:' file
<DATA>2020-04-13T08:59:05.427</DATA>

答案3

使用(以前称为 Perl_6)

raku -pe 's:g/ \<DATA ( <+[0..9]+[-T:.]>+ ) \s\/\> /{"<DATA>"~$0~"</DATA>"}/;'  

或者

raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = ["<DATA>"~$0~"</DATA>"];'   

输入示例:

<DATA2020-04-13T08:59:05.427 />  

示例输出:

<DATA>2020-04-13T08:59:05.427</DATA>

以上是编码的答案,Perl 编程语言家族的成员。上面的两个例子都有四个值得注意的一般特征:

  1. 无需猜测反斜杠字符:如果不是<alnum>(字母数字或下划线),则需要转义,

  2. /g像现在这样的正则表达式修饰符位于紧随 之后的表单global开头,前面有一个冒号。要么或有效,s///ss:globals:g

  3. Perl 的/x修饰符现在是 Raku 中的默认设置(允许正则表达式原子之间有自由的空格),并且

  4. Raku 中的字符串连接是通过~波浪号完成的。

上面的两个示例都使用枚举字符类<+[0..9]+[-T:.]>,它非常简单地由数字 [ 0..9] 加上四个字符 [ - T : .] 组成。此外,虽然上面的第一个示例遵循传统的s///替换习惯用法,但上面的第二个示例使用 Raku 的新“无反斜杠”替换格式(=中间有等号),一些读者可能会发现这种格式更具可读性。

最后,如果您对日期时间提取/修改有兴趣,Raku 可以满足您的需求:

~$ echo '<DATA2020-04-13T08:59:05.427 />' | raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = [DateTime($0~"Z")];'
2020-04-13T08:59:05.427000Z

~$ echo '<DATA2020-04-13T08:59:05.427 />' | raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = [DateTime(now) - DateTime($0~"Z")];'
54862286.622457

https://docs.raku.org/language/regexes#Enumerated_character_classes_and_ranges
https://docs.raku.org/routine/DateTime
https://raku.org

相关内容