fed*_*qui 3 regex bash date sed
假设我想通过date
命令将时间戳中的日期转换为另一种格式。在控制台中,我会说,date -d@<timestamp>
但我碰巧想对文本文件中的许多字段执行此操作。
使用e
to 在sed
( sed (GNU sed) 4.2.2
,实际上) 中执行我是说:
$ echo 1449158360 | sed -r 's#.*([0-9]{10}).*#date -d@\1 "+%Y";#e'
2015
Run Code Online (Sandbox Code Playgroud)
有效,不错!
现在我创建了一个虚拟文件myfile
:
my timestamp is 1449158360 but also I wonder what date was 1359199960.
Run Code Online (Sandbox Code Playgroud)
我想将其替换为相同但具有时间戳的相对年份:
my timestamp is 2015 but also I wonder what date was 2013.
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试运行与上面相同的命令,则会失败:
$ sed -r 's#([0-9]{10})#date -d@"\1" "+%Y";#e' myfile
sh: my: command not found
sh: but: command not found
Run Code Online (Sandbox Code Playgroud)
因为sed
将第一个单词解释为要执行的内容。
显然,如果我只获取这些数据而不是其他任何东西,它就可以工作:
$ sed -r 's#.*([0-9]{10}).*#date -d@"\1" "+%Y";#ge' myfile
2015
Run Code Online (Sandbox Code Playgroud)
所以我想知道:考虑到它被其他必须保持不变的文本包围,我应该怎么做才能调用date
捕获的组sed
并用它替换文本?
e
sed
替代切换适用sh -c
于不匹配的文本以及从以下命令中明显可见:
echo 'a 1449158360' | sed -r 's#([0-9]{10})#date -d@\1 "+%Y";#e'
sh: a: command not found
Run Code Online (Sandbox Code Playgroud)
因此,即使我们仅匹配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
Run Code Online (Sandbox Code Playgroud)
基本上我们<before>10-digits<after>
在这个正则表达式中匹配。
输出:
my timestamp is 2015 but also I wonder what date was 2013.
Run Code Online (Sandbox Code Playgroud)
为了澄清所使用的正则表达式,我创建了这个演示。
这绝不是e
模式问题的通用解决方案,请将其视为基于正则表达式的解决方法。