2016-07-25 15 views
0

我在bash中使用此命令執行操作時遇到了問題。以下是我:如何使用'while ..;做..;在bash中完成'

cat namelist | while read line; do awk '$1 == $line {print $0}' Jan.txt; done 

namelist是一個不重複的名稱列表,每行每名。而Jan.txt是信息像這樣的文件:

ermartin pts/10  Tue Jan 19 09:49 - 10:15 (00:26)  171.66.208.139 
sdou  pts/6  Tue Jan 19 01:52 - 22:20 (9+20:27) 131.243.186.99 
sdou  pts/2  Tue Jan 19 01:20 - 22:20 (9+20:59) 131.243.186.99 
phu  pts/2  Sat Jan 16 12:21 - 15:13 (02:52)  lbl-ipsec-7667.dhcp.lbl.gov 
phu  pts/2  Sat Jan 16 10:07 - 12:01 (01:54)  lbl-ipsec-7622.dhcp.lbl.gov 
sjames pts/5  Fri Jan 15 12:06 - 13:06 (01:00)  lakshmi.lbl.gov 
ermartin pts/2  Fri Jan 15 08:36 - 12:43 (04:07)  171.66.208.134 
ermartin pts/2  Fri Jan 15 08:31 - 08:36 (00:05)  171.66.208.134 
camitche pts/4  Thu Jan 14 15:18 - 20:47 (05:28)  171.66.208.134 
ermartin pts/2  Thu Jan 14 13:20 - 15:57 (02:36)  171.66.208.139 
ermartin pts/2  Thu Jan 14 12:35 - 13:00 (00:25)  171.66.208.139 
sjames pts/2  Thu Jan 14 06:17 - 06:27 (00:09)  phys1.als.lbl.gov 
sjames pts/2  Thu Jan 14 06:17 - 06:17 (00:00)  phys1.als.lbl.gov 
ermartin pts/0  Wed Jan 13 15:19 - 15:50 (00:31)  171.66.208.139 
ermartin pts/0  Wed Jan 13 07:55 - 08:09 (00:13)  c-24-130-14-154.hsd1.ca.comcast.net 

我只是想匹配namelist名到該文件,然後執行操作,在這個文件中的每一行信息,但是當我做了$1 == $line它說這是一個錯誤。我如何正確使用這個命令?

是否有可能也循環在過去幾個月,並打印出來作爲標題所以像:

[Jan] 
sjames ...hours 
sdou ...hours 

[Feb] 
sjames ...hours 
sdou ...hours 
+0

你爲什麼要每行運行一次'awk',而不是隻有一個'awk'調用處理整個輸入? –

+0

順便說一句,這個問題與'while read'循環無關;將變量傳入'awk'是一個問題。在'awk'$ 1 == $ line''中,'awk'無法訪問shell變量'line'的內容 - 即使沒有任何while循環,這仍然是真的。 –

+0

這也聽起來像你試圖「過濾」1月。txt文件僅用於'namelist'中的名稱。 'grep -F -f namelist Jan.txt'如何? ?祝你好運。 – shellter

回答

3

首先,awk和外殼不共享變量。但是,可以使用-v選項將shell變量轉換爲awk變量。下面的工作和你的代碼中唯一的變化是增加了-v line="$line"選項:

cat namelist | while read line; do awk -v line="$line" '$1 == line {print $0}' Jan.txt; done 

注意了awk引用line變量只是line沒有美元符號。

一個可能替代上述管道:

awk 'FNR==NR{a[$1]; next;} $1 in a' namelist Jan.txt 

這裏,關聯數組a跟蹤的是在namelist什麼名字,並用它來決定是否打印Jan.txt線。

grep -Ff namelist Jan.txt 

如果你不打算做數據的任何更多的處理(但據我瞭解,情況正好相反),那麼,作爲Shellter建議在評論中,上面的也被替換

如果要計算在名稱列表用戶使用的時間,然後再嘗試:

$ awk -F'[ +:()]+' 'FNR==NR{a[$1]; next;} !($1 in a){next} NF==13{b[$1]+=$12+60*$11} NF==14{b[$1]+=$13+60*($12+24*$11)} END{for (n in b)print n,b[n]}' namelist Jan.txt 

舉個例子,考慮這個名稱列表:

$ cat namelist 
sdou 
phu 

的計算時間爲:

$ awk -F'[ +:()]+' 'FNR==NR{a[$1]; next;} !($1 in a){next} NF==13{b[$1]+=$12+60*$11} NF==14{b[$1]+=$13+60*($12+24*$11)} END{for (n in b)print n,b[n]}' namelist Jan.txt 
phu 286 
sdou 28406 

對於可讀性,它可能是更容易看到相同的代碼分佈在多個線路:

awk -F'[ +:()]+' ' 
    FNR==NR{ 
    a[$1] 
    next 
    } 

    !($1 in a){ 
    next 
    } 

    NF==13{ 
    b[$1]+=$12+60*$11 
    } 

    NF==14{ 
    b[$1]+=$13+60*($12+24*$11) 
    } 

    END{ 
    for (n in b) 
     print n,b[n] 
    } 
    ' namelist Jan.txt 
phu 286 

要由用戶和按月跟蹤使用情況:

$ awk -F'[ +:()]+' 'FNR==NR{a[$1]; next;} !($1 in a){next} NF==13{b[$1"["$4"]"]+=$12+60*$11} NF==14{b[$1"["$4"]"]+=$13+60*($12+24*$11)} END{for (n in b)print n,b[n]}' namelist Jan.txt 
phu[Jan] 286 
sdou[Jan] 28406 
+0

我其實想要做的事情是這樣的: 對於文件中的名稱:for name_name namelist:if name == the_name:計算名稱和輸出到文件的時間 – Edccccch

+0

我想出瞭如何計算時間。這只是我如何擁有那些重要的循環,讓我感到困惑 – Edccccch

+0

這真棒! – Edccccch