剪切命令無法在對齊的列中正確提取字段

剪切命令無法在對齊的列中正確提取字段

我有一個文字文件,必須在其中剪切字段 3、4、5 和 8:

219 432 4567 Harrison     Joel     M 4540 Accountant      09-12-1985
219 433 4587 Mitchell     Barbara  C 4541 Admin Asst      12-14-1995
219 433 3589 Olson        Timothy  H 4544 Supervisor      06-30-1983
219 433 4591 Moore        Sarah    H 4500 Dept Manager    08-01-1978
219 431 4527 Polk         John     S 4520 Accountant      09-22-1998
219 432 4567 Harrison     Joel     M 4540 Accountant      09-12-1985
219 432 1557 Harrison     James    M 4544 Supervisor      01-07-2000

由於預設分隔符是製表符,因此提取欄位的命令為:

cut -f 3,4,5,8 filename

問題是輸出與原始文件內容相同。這裡發生了什麼事?為什麼這不起作用?

答案1

並非所有列之間的空格看起來都是製表符,因此cut無法執行您想要的操作。我建議awk改為使用。它比cut解析資料列(例如您想要完成的任務)更靈活:

$ awk '{print $3,$4,$5,$8}' data.txt

例子

$ awk '{print $3,$4,$5,$8}' data.txt 
4567 Harrison Joel Accountant
4587 Mitchell Barbara Admin
3589 Olson Timothy Supervisor
4591 Moore Sarah Dept
4527 Polk John Accountant
4567 Harrison Joel Accountant
1557 Harrison James Supervisor

您也可以使用以下命令來間隔輸出column

$ awk '{print $3,$4,$5,$8}' data.txt |column -t
4567  Harrison  Joel     Accountant
4587  Mitchell  Barbara  Admin
3589  Olson     Timothy  Supervisor
4591  Moore     Sarah    Dept
4527  Polk      John     Accountant
4567  Harrison  Joel     Accountant
1557  Harrison  James    Supervisor

您也可以僅使用awk和 來完成所有操作printf

$ awk '{printf "%s\t%-20s\t%s\n",$3,$4" "$5,$8}' data.txt 
4567    Harrison Joel           Accountant
4587    Mitchell Barbara        Admin
3589    Olson Timothy           Supervisor
4591    Moore Sarah             Dept
4527    Polk John               Accountant
4567    Harrison Joel           Accountant
1557    Harrison James          Supervisor

重新審視剪輯

上述方法做得很好,但它們不處理特定列的值中存在空格的任何行。例如,包含“Dept Manager”的行被截斷為“Dept”。

如果可以保證資料是如圖所示的結構,我們可以使用,cut但我們可以只使用字元的實際位置來顯示,而不是在分隔符號上分割。

例子

這將從文件中剪切文字data.txt並列印位置 9 到 13、14 到 35 等位置的所有內容。

$ cut -c 9-13,14-35,43-58 data.txt 
4567 Harrison     Joel     Accountant      
4587 Mitchell     Barbara  Admin Asst      
3589 Olson        Timothy  Supervisor      
4591 Moore        Sarah    Dept Manager    
4527 Polk         John     Accountant      
4567 Harrison     Joel     Accountant      
1557 Harrison     James    Supervisor      

重溫 awk

也可以使 awk 根據文字的位置而不是分隔符號來提取文字。雖然它更冗長,但為了完整起見,這裡是如何實現的。

$ awk '{
    printf "%s\t%-20s\t%s\n",substr($0,9,5),substr($0,14,22),substr($0,43,16)
  }' data.txt
4567    Harrison     Joel       Accountant      
4587    Mitchell     Barbara    Admin Asst      
3589    Olson        Timothy    Supervisor      
4591    Moore        Sarah      Dept Manager    
4527    Polk         John       Accountant      
4567    Harrison     Joel       Accountant      
1557    Harrison     James      Supervisor      

awk 字段寬度

如果您使用的是 GNU 的變體,awk則可以使用該變數FIELDWIDTHS來指定每個欄位的靜態大小。substr如果您有權訪問它,那麼這比該方法要乾淨得多。您也可以有效地將原本會被解析為單獨欄位的欄位黏合在一起。

$ awk 'BEGIN { FIELDWIDTHS="4 4 5 24 5 16 11" }{ print $3,$4,$5,$6 }' data.txt 
4567  Harrison     Joel     M  4540  Accountant      
4587  Mitchell     Barbara  C  4541  Admin Asst      
3589  Olson        Timothy  H  4544  Supervisor      
4591  Moore        Sarah    H  4500  Dept Manager    
4527  Polk         John     S  4520  Accountant      
4567  Harrison     Joel     M  4540  Accountant      
1557  Harrison     James    M  4544  Supervisor      

答案2

我的猜測是我不認為這些是標籤。我不認為它們是選項卡的原因是因為當我複製貼上文件並手動對欄位進行製表時,似乎cut -f 3,4,5,8 filename工作正常。cat filename | awk '{print $3, $4, $5, $8}'如果您不想重新製作欄位和值,您最好這樣做。

相關內容