我有一个有趣的问题,使用仅使用sed 将短月份字符串(ex“Oct”)替换为相应的数字值(ex“10),给出如下字符串:
Oct 14 09:23:35 some other input
直接通过sed
替换为:
14-10-2013 09:23:25 some other input
以下所有内容实际上都与解决月份字符串的小问题无关 - >数字转换;我更感兴趣的是理解我在尝试用sed解决这个问题时遇到的一些奇怪的行为。
没有任何此字符串替换的尝试(echo
语句代替我脚本中的实际输入):
...
MMM_DD_HH_mm_SS="([A-Za-z]{3}) ([0-9]{2}) (.+:[0-9]{2})"
echo "Oct 14 09:23:35 some other input" | sed -r "s/$MMM_DD_HH_mm_ss (.+)/\2-\1-\3 \4/"
然后如何将反向引用\1
转换为数字。当然,人们会考虑使用命令插值和反向引用作为参数:
...
TestFunc()
{
echo "received input $1$1"
}
...
echo "Oct 14 09:23:35 some other input" | sed -r "s/$MMM_DD_HH_mm_ss (.+)/\2-$(TestFunc \\1)-\3 \4/"
其中TestFunc
将是date
命令的变体(由Jotne在下面提出),echo
'd日期时间组作为输入。这里TestFunc只是一个echo
,因为我对函数认为是$1
的价值的行为更感兴趣。
在这种情况下,带有sed
的{{1}}会产生输出:
TestFunc
这表明sed实际 在命令替换14-received input OctOct-09:23:35 some other input
中插入反向引用\1
,以便$(...)
处理(似乎接收TestFunc
作为局部变量\1
)。
但是,所有使用本地$1
做更多事情的尝试都会失败。例如:
$1
返回:
TestFunc()
{
echo "processed: $1$1" > tmp.txt # Echo 1
if [ "$1" == "Oct" ]; then
echo "processed: 10"
else
echo "processed: $1$1" # Echo 2
fi
}
14-processed: OctOct-09:23:35 some other input
已被替换为Echo 2,但$1
包含值tmp.txt
;好像没有将反向引用插入到命令替换中。即使更奇怪,processed: \1\1
条件也会因if
!=“10月”而失败,但它会落到$1
语句中,表明echo
=“10月”。
我的问题是为什么反向引用插入工作在Echo 2而不是Echo 1?我怀疑反向引用插入根本不起作用(假设$1
中的if
语句失败),而是发生了一些微妙的事情,这使得替换似乎在以下情况下正常工作回声2;什么是微妙的?
进一步思考后,我相信我明白了发生了什么:
TestFunc
作为文字\\1
传递给命令替换子例程/子函数。这就是子函数中的相等测试失败的原因。
但\1
函数 正确处理字符串echo
为\\1
。因此$1
将命令替换的结果返回echo "aa$1aa"
sed
。其他功能(例如aa\1aa
)也“看到”rev
为$1
。
\1
然后将sed
中的\1
插入为aa\1aa
或其他任何反向引用,以便将Oct
返回给用户。
由于正则表达式中的命令替换显然有效,如果aaOctaa
替换sed
(或\\1
,无论如何)的值,使用后面的 ,那将会非常酷strong>执行命令替换\1
;这会显着增加sed的力量......
答案 0 :(得分:1)
使用正确的工具:
date -d "Oct 14 09:23:35" +"%d-%m-%Y %H:%M:%S"
14-10-2013 09:23:35
日期会读取您的输入并将其转换为您喜欢的任何格式
答案 1 :(得分:0)
这可能适合你(GNU sed):
s/$/\nJan01...Oct10Nov11Dec12/;s/(...) (..) (..:..:.. .*)\n.*\1(..).*/\2-\4-2013 \3/;s/\n.*//' file
在行尾添加查找并使用后引用进行匹配,确保在所有情况下都删除查找表。
以下是将反向引用传递给函数的示例:
f(){ echo "x$1y$1z"; }
echo a b c | sed -r 's/(.) (.) (.)/'"$(f \\2)"'/'
返回:
xbybz
HTH