打印具有最高值的行
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
说明
这里我们使用了一种叫做Schwartzian transform的技术。
您的问题含糊不清,因为我们不知道您如何认为 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
添加一个额外的字段作为分区标识符后,我们可以使用sort
、awk
和cut
的组合轻松解决您的问题。
在 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
给出以下源自 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
说明
这里我们使用了一种叫做Schwartzian transform的技术。
您的问题含糊不清,因为我们不知道您如何认为 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
添加一个额外的字段作为分区标识符后,我们可以使用
sort
、awk
和cut
的组合轻松解决您的问题。
在 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.
以下是取自 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 ofkey="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