打印具有最高值的行

Printing row with highest value

给出以下源自 df -P | awk '!/udev|boot|tmpfs|none/ && NR>1 {printf ("%-10s\t%-10s\t%-10s\n", , , )}' | grep -wv / 的输出。

/dev/sda2       576075280       /hdd
/dev/sda1       1344681704      /home
/dev/vda2       2468687261      /media/user/backup
/dev/vda1       823581356       /media/user/movie
/dev/sdb2       676075280       /media/user/db2
/dev/sdb1       1691481049      /media/user/db1

我想 select 具有每个分区中最大存储的行,所需的输出将是。

/dev/sda1       1344681704      /home
/dev/vda2       2468687261      /media/pi/backup
/dev/sdb1       1691481049      /media/pi/db1

解决方案

cat input.txt |
  awk '{print substr(, 1, match(, "[[:digit:]]") - 1), [=10=]}' |
  sort -k1,1 -k3,3nr |
  awk 'id!={ print; id = }' | cut -d ' ' -f2-

输入

λ cat input.txt 
/dev/sda2       576075280       /hdd
/dev/sda1       1344681704      /home
/dev/vda2       2468687261      /media/user/backup
/dev/vda1       823581356       /media/user/movie
/dev/sdb2       676075280       /media/user/db2
/dev/sdb1       1691481049      /media/user/db1

输出

/dev/sda1       1344681704      /home
/dev/sdb1       1691481049      /media/user/db1
/dev/vda2       2468687261      /media/user/backup

说明

  1. 这里我们使用了一种叫做Schwartzian transform的技术。

  2. 您的问题含糊不清,因为我们不知道您如何认为 2 个分区相同。我在这里使用命令 awk '{print substr(, 1, match(, "[[:digit:]]") - 1), [=14=]}',但您可以更改它以满足您的需要。

    λ cat input.txt | awk '{print substr(, 1, match(, "[[:digit:]]") - 1), [=13=]}'                                                                     
    /dev/sda /dev/sda2       576075280       /hdd
    /dev/sda /dev/sda1       1344681704      /home
    /dev/vda /dev/vda2       2468687261      /media/user/backup
    /dev/vda /dev/vda1       823581356       /media/user/movie
    /dev/sdb /dev/sdb2       676075280       /media/user/db2
    /dev/sdb /dev/sdb1       1691481049      /media/user/db1
    
  3. 添加一个额外的字段作为分区标识符后,我们可以使用sortawkcut的组合轻松解决您的问题。

在 Linux 中,您可以只使用 lsblk 而不是 df 来查找每个磁盘的最大分区:

lsblk -nPpbo KNAME,SIZE,PKNAME,MOUNTPOINT |

awk -F'="|" ?' -v OFS='\t' '
    {
        kname =        # device name, for ex. /dev/sda1
        size =         # size of the device, in Bytes
        pkname =       # parent device name, for ex. /dev/sda 
        mountpoint =   # where the device is mounted, absolute path
    }

    pkname !~ "^/" { next }
    mountpoint !~ "^/" { next }
    mountpoint == "/" { next } # not sure why you want to exclude /

    size > sizes[pkname] {
        knames[pkname] = kname
        sizes[pkname] = size
        mountpoints[pkname] = mountpoint
    }

    END {
        for (pkname in knames)
            print knames[pkname], sizes[pkname], mountpoints[pkname]
    }
'

备注: 大小将以字节显示,而不是 512 或 1024 块,字段中可能有问题的字符(主要在挂载点)将使用两位十六进制符号 \xHH 进行转义。恕我直言,这两个都是好点,因为您将能够使用 bash.

准确读取和转义生成的 TSV

以下是取自 lsblk 文档的相关选项:

-b, --bytes
       Print the SIZE column in bytes rather than in a human-readable format.
-n, --noheadings
       Do not print a header line.
-P, --pairs
       Produce output in the form of key="value" pairs.
       All potentially unsafe characters are hex-escaped (\x<code>).
-p, --paths
       Print full device paths.
-o, --output list
       Specify which output columns to print. [...]

       KNAME internal kernel device name
       MOUNTPOINT where the device is mounted
       SIZE size of the device
       PKNAME internal parent kernel device name