2

我遇到了一个有趣的问题,仅使用 sed将短月份字符串(例如“Oct”)替换为相应的数值(例如“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/"

将'd 日期时间组作为输入TestFunc的命令变体date(如下 Jotne 建议的)在哪里。echo这里 TestFunc 只是一个,echo因为我对函数认为的值的行为更感兴趣$1

在这种情况下,sedwithTestFunc产生输出:

14-received input OctOct-09:23:35 some other input

这表明 sed 实际上\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

$1已被代入 Echo 2,但tmp.txt包含值processed: \1\1; 就好像反向引用没有被插入到命令替换中一样。更奇怪的是,if条件以 != "Oct" 失败$1,但它落入指示= "Oct"的echo语句。$1

我的问题是为什么反向引用插入在 Echo 2 而不是 Echo 1 的情况下有效?我怀疑反向引用插入根本不起作用(鉴于ifin 中的语句失败TestFunc),而是发生了一些微妙的事情,使得替换在 Echo 2 的情况下似乎正常工作;那是什么微妙之处?

解决方案

经过进一步思考,我相信我了解发生了什么:

  • \\1作为文字传递给命令替换子例程/子函数\1。这就是子函数中的相等测试失败的原因。

  • 但是该echo函数正确地将字符串处理\\1$1. 所以echo "aa$1aa"将命令替换的结果返回到sedas aa\1aa。其他功能,例如rev“see” $1as \1

  • sed然后插入\1作为或任何反向引用aa\1aaOct以返回aaOctaa给用户。

由于正则表达式中的命令替换显然有效,如果在执行命令替换之前用反向引用替换(或,其他)sed的值会非常酷;这将显着增加 sed 的力量......\\1\1$(...)

4

2 回答 2

1

使用正确的工具:

date -d "Oct 14 09:23:35" +"%d-%m-%Y %H:%M:%S"
14-10-2013 09:23:35

日期确实会读取您的输入并将其转换为您喜欢的任何格式

于 2013-10-14T17:01:07.427 回答
1

这可能对您有用(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

高温高压

于 2013-10-14T20:38:34.250 回答