AWK-更改第二次会议的日期

AWK-更改第二次会议的日期,awk,gsub,Awk,Gsub,我有一个文件: pablo tty8 Thu Nov 1 12:51:21 2012 still logged in (unknown tty8 Thu Nov 1 12:50:57 2012 - Thu Nov 1 12:51:21 2012 (00:00) pablo tty2 Thu Nov 1 12:50:39 2012 still logged in pablo tty7 Thu Nov 1 12:49:45 2012 - Thu Nov 1 12:50:56 2012 (00:

我有一个文件:

pablo tty8 Thu Nov 1 12:51:21 2012 still logged in 
(unknown tty8 Thu Nov 1 12:50:57 2012 - Thu Nov 1 12:51:21 2012 (00:00) 
pablo tty2 Thu Nov 1 12:50:39 2012 still logged in 
pablo tty7 Thu Nov 1 12:49:45 2012 - Thu Nov 1 12:50:56 2012 (00:01) 
(unknown tty7 Thu Nov 1 12:34:32 2012 - Thu Nov 1 12:49:45 2012 (00:15)
我想在上述日期替换文件一秒钟。我想打印:

pablo tty8 1351770681 still logged in 
(unknown tty8 1351770657 - 1351770681 (00:00) 
pablo tty2 1351770639 still logged in 
pablo tty7 1351770585 - 1351770656 (00:01) 
(unknown tty7 1351769672 - 1351770585 (00:15)
我试过这个命令:

gawk --posix 'function my()
{"date -d \047"$0"\047 +%s" | getline b; 
gsub( /[A-Za-z]{3} [A-Za-z]{3} [0-9] ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/,b ); print}
{ my() }' file
:%s/\v\w+\s\w+\s\d+\s\d+:\d+:\d+\s\d+/\=system('date +%s -d"'.submatch(0).'" | tr -d "\n"')/g
上述命令不起作用:

$ gawk --posix 'function my()
> {"date -d \047"$0"\047 +%s" | getline b; 
> gsub( /[A-Za-z]{3} [A-Za-z]{3} [0-9] ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/,b ); print}
> { my() }' ta
date: błędna data: `pablo tty8 Thu Nov 1 12:51:21 2012 still logged in '
pablo tty8  still logged in 
(unknown tty8 1351897200 - 1351897200 (00:00) 
date: błędna data: `pablo tty2 Thu Nov 1 12:50:39 2012 still logged in '
pablo tty2 1351897200 still logged in 
date: błędna data: `pablo tty7 Thu Nov 1 12:49:45 2012 - Thu Nov 1 12:50:56 2012 (00:01) '
pablo tty7 1351897200 - 1351897200 (00:01) 
(unknown tty7 1351897200 - 1351897200 (00:15)
如何改进上述命令


谢谢您的帮助。

这里有一种使用GNU awk的方法。运行方式如下:

awk -f script.awk file.txt
script.awk的内容

{
    line = ($0 ~ /still logged in/) ? "still logged in" : "-" OFS getstamp(10) OFS $NF
    print $1, $2, getstamp(4), line
} 

function getstamp(i) {

    split($(i + 2), T, ":")

    Y = $(i + 3)
    M = convert($i)
    D = $(i + 1)

    hrs = T[1] + 9
    min = T[2]
    sec = T[3]

    return(mktime(sprintf("%d %d %d %d %d %d", Y, M, D, hrs, min, sec)))
}

function convert(month) {

    return(((index("JanFebMarAprMayJunJulAugSepOctNovDec", month) - 1) / 3) + 1)
}
结果:

pablo tty8 1351770681 still logged in
(unknown tty8 1351770657 - 1351770681 (00:00)
pablo tty2 1351770639 still logged in
pablo tty7 1351770585 - 1351770656 (00:01)
(unknown tty7 1351769672 - 1351770585 (00:15)

如果已安装
vim
,请尝试以下命令:

gawk --posix 'function my()
{"date -d \047"$0"\047 +%s" | getline b; 
gsub( /[A-Za-z]{3} [A-Za-z]{3} [0-9] ([0-9]{2}:){2}[0-9]{2} [0-9]{4}/,b ); print}
{ my() }' file
:%s/\v\w+\s\w+\s\d+\s\d+:\d+:\d+\s\d+/\=system('date +%s -d"'.submatch(0).'" | tr -d "\n"')/g

这个想法很简单<代码>vim可以非常快速。

这里有一个在
awk
中使用
日期
的解决方案(可能仅限于
gawk

输出:

pablo tty8 1351745481 still logged in 
(unknown tty8 1351745457 - 1351745457 (00:00) 
pablo tty2 1351745439 still logged in 
pablo tty7 1351745385 - 1351745456 (00:01) 
(unknown tty7 1351744472 - 1351744472 (00:15)
注:

  • match
    -
    substr
    组合用于提取包含日期的子字符串
  • 使用
    date
    将日期子字符串转换为秒格式(
    +%s
    ),并将秒分配给
    date\u sec
  • 用第二个格式日期替换字符串格式日期
  • 迭代直到未找到匹配项(
    match
    如果未找到匹配项,则返回0,从而终止
    while
    循环)
  • 间隔表达式仅允许在带有
    --re Interval
    --posix
    选项的
    gawk
    中使用

  • 谢谢你提供了一个好的解决方案。我只是想知道你是否能按我的方式来做?@Tedee12345:我已经更新了脚本,以产生你所需要的准确结果。我不确定为什么需要将时间调整为9小时,但它会给你想要的结果。另外,我会避免像您尝试的那样调用
    date
    awk
    具有一些良好的内置时间函数,并且不需要使用
    date
    。谢谢你,伙计!很高兴我能帮忙。干杯。请不要重复发布:@glenn jackman,很抱歉在另一个论坛中重复了这个主题。它不仅仅是gawk,它可以在任何POSIX awk和任何其他支持重新间隔的awk中工作。您添加了--posix,因此gawk可以正确地处理像{3}这样的重新间隔,但仅供参考,这是较新的gawk版本中的默认行为,在较旧的版本中,最好使用--RE interval而不是--posix,因为后者禁用了所有其他GNU awk扩展,如gensub()和时间函数。最后,您不需要使用gawk调用外部“date”命令,因为它有自己的内置时间函数。