我有一个如下文件:
[2024-01-20 15:23:00] hello world
[2024-01-20 15:42:00] bye
[2024-01-20 15:43:00] foo bar
...
此文件中的日期为 UTC+1,我想将其转换为 UTC
我尝试使用sed
捕获组:
cat file | sed -E "s/(([0-9]+-[0-9]+-[0-9]+)? ?([0-9]+:[0-9]+:[0-9]+))/$(date -d "\1 UTC+1" +%H:%M:%S -u)/g"
但我得到了:
date: invalid date ‘\\1 UTC+1’
我曾尝试以下替换\1
:
"\1"
'\1'
\\1
"\\1"
'\\1'
以上都不起作用。
为了测试我使用这个单行:
echo '19:40:14 foo bar' | sed -E "s/([0-9:]+)/$(date -d "\1 UTC+1" -u +%R)/g"
期望结果:19:40:14
->18:40:14
时区为 UTC+1
我愿意使用其他东西来代替sed
答案1
使用 GNU sed 作为其e
修饰符
sed -E 's/\[([^]]+)\](.*)/date -ud "\1+01:00" "+[%F %T\2"/e' file
# ........................................................^
[2024-01-20 14:23:00] hello world
[2024-01-20 14:42:00] bye
[2024-01-20 14:43:00] foo bar
答案2
这种$(...)
方法永远不会奏效,因为这种扩展由 shell 处理,而 'sed' 不是 shell 的一部分,这意味着$
命令行中的所有替换都会发生前'sed' 甚至根本就运行 – 并且整个命令只执行一次。
(它才不是在 'sed' 和 shell 之间来回切换,并针对每个正则表达式匹配重新展开,而且所有操作都不会“同时”发生;有一定的操作顺序。)
为了使其工作,日期调整需要在同一个程序中完成。'sed' 没有这样的功能;AWK 可能有,尽管其他一些语言可能会更方便。
用 Python、Ruby、PHP 或 Perl 编写一个脚本,从 STDIN 读取每一行并执行正则表达式替换 - 所有这些语言都有使用“回调函数”作为正则表达式替换的方法(例如,在 Python 中,你可以直接将函数作为参数传递,在 Perl 中,你可以使用/e
正则表达式选项)。
(或者执行一切包括正则表达式在 Bash 中,使用while read
循环和 Bash 的[[ a =~ b ]]
正则表达式匹配运算符。)