假设我想通过date
命令将时间戳中的日期转换为另一种格式。在控制台中我会说date -d@<timestamp>
但我碰巧想对文本文件中的许多字段执行此操作。
使用e
执行sed
(sed (GNU sed) 4.2.2
,实际上)我说:
$ echo 1449158360 | sed -r 's#.*([0-9]{10}).*#date -d@\1 "+%Y";#e'
2015
很有效!
现在我创建了一个虚拟文件myfile
:
my timestamp is 1449158360 but also I wonder what date was 1359199960.
我希望将其替换为相同但具有时间戳的相对年份:
my timestamp is 2015 but also I wonder what date was 2013.
但是,如果我尝试运行与上面相同的命令,则会失败:
$ sed -r 's#([0-9]{10})#date -d@"\1" "+%Y";#e' myfile
sh: my: command not found
sh: but: command not found
因为sed
将第一个单词解释为要执行的内容。
显然,如果我只是获取这些数据,那么它就可以了:
$ sed -r 's#.*([0-9]{10}).*#date -d@"\1" "+%Y";#ge' myfile
2015
所以我想知道:我应该怎么做才能在date
中针对捕获的群组调用sed
,并用它替换文字,考虑到它被其他文本包围,必须保持不变?
答案 0 :(得分:4)
e
切换sed
替换将sh -c
应用于不匹配的文本,以及此命令中显而易见:
echo 'a 1449158360' | sed -r 's#([0-9]{10})#date -d@\1 "+%Y";#e'
sh: a: command not found
即使我们仅匹配1449158360
,但sh -c
正在a 1449158360
上运行。
由于sed
中缺少非贪婪和前瞻性正则表达式,此解决方法正则表达式可能看起来很疯狂,但这就是如何在文件中为多个匹配输入运行它,如问题所示:
sed -r 's#(([^0-9][0-9]{0,9})*)(\b[0-9]{10}\b)(([0-9]{0,9}[^0-9])*)#printf "%s%s%s" "\1" $(date -d@\3 "+%Y") "\4";#ge' file
基本上我们在此正则表达式中匹配<before>10-digits<after>
。
<强>输出:强>
my timestamp is 2015 but also I wonder what date was 2013.
为了澄清我使用的正则表达式,我创建了this demo。
这绝不是e
模式问题的通用解决方案,将其视为基于正则表达式的解决方法。
答案 1 :(得分:0)
正如你所说,使用e标志myfile
将所有句子作为执行的句子。
转变可能就是这样。
将echo "my timestamp is 1449158360 but also I wonder what date was 1359199960."
更改为:
sed -r 's#([0-9]{10})#\`date -d@\1 "+%Y"\`#ge' myfile
然后:
sed -r 's/ $/,/'
希望有帮助