Awk

如何使用格式設置 awk 和 printf 列並包括 9 號之後的所有列

  • March 10, 2017

我有下面的腳本來列印從第 1 列到第 9 列的所有指定列,使用 printf 進行格式化,但是我想列印第 9 列之後的任何列,但我不確定該怎麼做

pwd=`pwd`
#Megabytes
max_size_1=`ls -ltr "$pwd" | grep -v "total" | awk '{print $1}' | sort -n | tail -1 | wc -m`
max_size_2=`ls -ltr "$pwd" | grep -v "total" | awk '{print $2}' | sort -n | tail -1 | wc -m`
max_size_3=`ls -ltr "$pwd" | grep -v "total" | awk '{print $3}' | sort -n | tail -1 | wc -m`
max_size_4=`ls -ltr "$pwd" | grep -v "total" | awk '{print $4}' | sort -n | tail -1 | wc -m`
max_size_5=`ls -ltr "$pwd" | grep -v "total" | awk '{$5=sprintf("%.0f M", $5/1024^2)} 1' | awk '{print $5}' | sort -n | tail -1 | wc -m`


ls -ltr "$pwd" | grep -v "total" | awk '{$5=sprintf("%.0f M", $5/1024^2)} 1' | eval "awk '{printf \"%$max_size_1-s %$max_size_2-s %$max_size_3-s %$max_size_4-s %$max_size_5-s %-3s %-3s %-3s %-6s\\n\", \$1, \$2, \$3, \$4, \$5, \$6, \$7, \$8, \$9}'"

輸出是:

-rwxr-xr-x  1  informix  informix  0  M   Mar 1   13:45 
-rwxr-xr-x  1  informix  informix  0  M   Mar 1   13:45 
-rwxr-xr-x  1  informix  informix  0  M   Mar 1   13:46 
-rwxr-xr-x  1  informix  informix  0  M   Mar 9   10:51 
-rw-r-----  1  informix  informix  0  M   Mar 9   12:36 
-rwxrwxrwx  1  informix  informix  0  M   Mar 9   13:01

我想要什麼:

-rwxr-xr-x  1  informix  informix  0  M   Mar 1   13:45 ls-ltrg
-rwxr-xr-x  1  informix  informix  0  M   Mar 1   13:45 ls-ltrk
-rwxr-xr-x  1  informix  informix  0  M   Mar 1   13:46 ls-ltrb
-rwxr-xr-x  1  informix  informix  0  M   Mar 9   10:51 ls-ltrm
-rw-r-----  1  informix  informix  0  M   Mar 9   12:36 split word
-rwxrwxrwx  1  informix  informix  0  M   Mar 9   13:01 test.sh

它應該列印九個偶數文件或此後拆分的名稱之後的所有列。

我發現這是一個有趣的問題,主要是作為 awk 的學習機會。

穩健地解析 ls棘手,不推薦,所以我不會在這裡討論這些細節。如果您的文件名從不包含任何換行符,那麼您可以使用以下 awk 腳本來完成您在單獨的部分中所做的所有工作:

  • 找出“總”行
  • 獲取每個欄位的長度
  • 動態格式化列

… 無需多次呼叫 ls、grep、awk、sort、tail 和 wc,無需使用eval.

由於預設ls列出目前目錄 ( pwd),因此我也將其刪除。

一些隨機筆記:

  • 我在第一次使用awk時沒有初始化i為零,所以我在 BEGIN 塊中將其強制為零
  • grep -v total部分發生在一行中:/^total / { next; }
  • 您的實際問題的實際解決方案是在循環中,我們在第 9 列中合併文件名資訊 .. NF。for
  • 格式分為兩部分:forEND 塊中的第一個循環確定我們需要的寬度;第二個for循環使用*格式說明符來完成真正的工作——通過在實際值之前傳遞所需的寬度。

這是生成的腳本/程式碼:

ls -ltr | awk '
       BEGIN {
               i=0;
       }

       /^total / { next; }
       {
               perms[i]=$1
               links[i]=$2
               owner[i]=$3
               group[i]=$4
               $5=sprintf("%.0f M", $5/1024^2)
               size[i]=$5
               date[i]=$6 " " $7 " " $8
               for(x=9; x <= NF; x++) name[i] = name[i] " " $x
               i++
       }

       END {
               for(j=0;j<i;j++) {
                       if (length(perms[j]) > maxperms) maxperms = length(perms[j])
                       if (length(links[j]) > maxlinks) maxlinks = length(links[j])
                       if (length(owner[j]) > maxowner) maxowner = length(owner[j])
                       if (length(group[j]) > maxgroup) maxgroup = length(group[j])
                       if (length(size[j]) > maxsize) maxsize = length(size[j])
               }
               for(j=0;j<i;j++) {
                       printf "%-*s %-*s %-*s %-*s %-*s %s %s\n",
                               maxperms, perms[j],
                               maxlinks, links[j],
                               maxowner, owner[j],
                               maxgroup, group[j],
                               maxsize, size[j],
                               date[j],
                               name[j]
               }
       }
       '

非常感謝 G-Man,他提供了現成的備忘單供我用於awk 的動態列格式化

引用自:https://unix.stackexchange.com/questions/350233