2012-11-03 41 views
2

日我有一個文件:AWK - 改變的第二

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 

上面的命令不起作用:

$ 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) 

如何提高上面的命令?

謝謝你的幫助。

+2

請不要雙重職務: http://unix.stackexchange.com/q/53724/4667 –

+0

@glenn jackman,對不起,在另一個論壇中重複的話題。 – Tedee12345

回答

2

以下是使用GNU awk的一種方法。運行,如:中script.awk

awk -f script.awk file.txt 

內容:

{ 
    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) 
+0

謝謝你的解決方案。我只是想知道你能否按我的方式去做? – Tedee12345

+0

@ Tedee12345:我已更新腳本以產生您需要的確切結果。我不知道爲什麼時間需要調整九點,但它會給你你想要的結果。另外,我會避免像你想要做的那樣調用'date'。 'awk'有一些很好的內部時間函數,'date'是不必要的。 HTH。 – Steve

+0

再次感謝您的幫助。 – Tedee12345

5

如果您已經安裝vim,試試這個命令:

:%s/\v\w+\s\w+\s\d+\s\d+:\d+:\d+\s\d+/\=system('date +%s -d"'.submatch(0).'" | tr -d "\n"')/g 

的想法是很簡單。 vim可以很快。

+0

就在我認爲自己做得很好的時候+1 – Steve

+0

謝謝你的好解決方案 – Tedee12345

1

下面是使用的溶液dateawk(可能gawk只)

awk --posix ' 
{ 
    while(match($0,/([[:alpha:]]{3}){2}[^[:alpha:]]+[0-9]{4}/)){ 
    date_str=substr($0, RSTART, RLENGTH) 
    "date -d \""date_str"\" +%s" | getline date_sec 
    sub(date_str,date_sec,$0) 
    } 
    print 
} 
' $1 

輸出:

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) 

注:

  1. match - substr組合被用於提取的子含有th日期。
  2. 使用date轉換日期字符串到秒的格式(+%s)並分配秒,date_sec
  3. 替換字符串格式的日期和第二格式的日期。
  4. 迭代,直到沒有發現匹配(match返回0,如果沒有找到匹配其終止while環)
  5. 間隔表達式只允許gawk--re-interval--posix選項
+0

謝謝你的另一個好的解決方案。 – Tedee12345

+0

它不僅僅是gawk,它可以在任何支持RE間隔的POSIX awk和awk中工作。你添加了--posix,所以gawk會正確處理像{3}那樣的RE間隔,但是FYI是新版gawk版本中的默認行爲,在舊版本中,使用--re-interval比--posix更好,因爲後者會禁用所有其他GNU awk擴展,如gensub()和時間函數。最後,你不需要用gawk調用外部的「date」命令,因爲它有它自己的內置時間函數。 –