正确的工具,用于从 blkid 程序的输出中过滤 UUID(使用 grep、cut 或 awk,e.t.c)



我想过滤 blkid 的输出以获取 UUID。

blkid的输出看起来像

个案1:-

$ blkid
/dev/sda2: LABEL="A" UUID="4CC9-0015"
/dev/sda3: LABEL="B" UUID="70CF-169F"
/dev/sda1: LABEL=" NTFS_partition" UUID="3830C24D30C21234"

在某些情况下,blkid 的输出看起来像

案例2:-

$ blkid
/dev/sda1: UUID="d7ec380e-2521-4fe5-bd8e-b7c02ce41601" TYPE="ext4" 
/dev/sda2: UUID="fc54f19a-8ec7-418b-8eca-fbc1af34e57f" TYPE="ext4" 
/dev/sda3: UUID="6f218da5-3ba3-4647-a44d-a7be19a64e7a" TYPE="swap" 

我想过滤掉 UUID。

使用grep切割的组合可以完成

/sbin/blkid | /bin/grep 'sda1' | /bin/grep -o -E 'UUID="[a-zA-Z|0-9|-]*' | /bin/cut -c 7-

我尝试使用awk,grepcut如下来过滤UUID

$ /sbin/blkid | /bin/grep 'sda1' | /usr/bin/awk '{print $2}' | /bin/sed 's/"//g' | cut -c 7-
7ec380e-2521-4fe5-bd8e-b7c02ce41601

上面的命令(使用 awk)是不可靠的,因为有时blkid程序的输出中可能会出现一个额外的字段,例如 LABEL,如上面的输出所示。

使用awk创建可靠工作的命令的最佳方法是什么? 请发布是否有任何其他优雅的方法退出使用bin和核心实用程序的工作。我不想使用 perl 或 python,因为这必须在 busybox 上运行。

注意:-我正在使用busyboxblkid,其中/dev/sda1不能作为参数传递到(我使用的版本不支持它),因此 grep 过滤行。

更新 :- 添加了案例 2: -输出以显示字段位置不能依赖。

你为什么要让它变得如此复杂?

试试这个:

# blkid -s UUID -o value
d7ec380e-2521-4fe5-bd8e-b7c02ce41601
fc54f19a-8ec7-418b-8eca-fbc1af34e57f
6f218da5-3ba3-4647-a44d-a7be19a64e7a

或者这个:

# blkid -s UUID -o value /dev/sda1
d7ec380e-2521-4fe5-bd8e-b7c02ce41601

如果没有,请安装正确的 blkid 软件包:

sudo apt-get install util-linux
sudo yum install util-linux

对于所有 UUID,您可以执行以下操作:

$ blkid | sed -n 's/.*UUID="([^"]*)".*/1/p' 
d7ec380e-2521-4fe5-bd8e-b7c02ce41601
fc54f19a-8ec7-418b-8eca-fbc1af34e57f
6f218da5-3ba3-4647-a44d-a7be19a64e7a

比如说,仅适用于特定的 sda1:

$ blkid | sed -n '/sda1/s/.*UUID="([^"]*)".*/1/p' 
d7ec380e-2521-4fe5-bd8e-b7c02ce41601

sed 命令尝试将 UUID 关键字后面的双引号中存在的内容分组,并将整行替换为标记。

这是一个简短的awk解决方案:

blkid | awk 'BEGIN{FS="[="]"} {print $(NF-1)}'

输出:

4CC9-0015
70CF-169F
3830C24D30C21234

解释:

  • BEGIN{FS="[="]"}: 使用="作为分隔符
  • {print $(NF-1)}: 字段数的NF个支架;在这里我们打印倒数第二个字段
  • 这是基于 blkid 输出的一致结构:引号中的UUID位于每行的末尾。

或者:

blkid | awk 'BEGIN{FS="="} {print $NF}' | sed 's/"//g'

data.txt

/dev/sda2: LABEL="A" UUID="4CC9-0015"
/dev/sda3: LABEL="B" UUID="70CF-169F"
/dev/sda1: LABEL=" NTFS_partition" UUID="3830C24D30C21234"

awksed组合

cat data.txt | awk 'BEGIN{FS="UUID";RS="n"} {print $2}' | sed -e 's/=//'  -e 's/"//g'

解释:

  1. 将字段分隔符设置为字符串"UUID",$2将给出其余输出
  2. 然后使用 sed 删除=",如图所示,-e是一个开关,以便您可以在一个开关中提供多个 SED 命令/表达式。
  3. 所有出现的"都使用结束g选项(即全局)删除。

这个问题有一个"e.t.c",所以我假设python是选项之一;)

#!/usr/bin/env python3
import subprocess, re, json
# get blkid output
blkid = subprocess.check_output(["blkid"]).decode('utf-8')

devices = []
for line in [x for x in blkid.split('n') if x]:
parameters = line.split()
for idx, parameter in enumerate(parameters):
if idx is 0:
devices.append({"DEVICE": re.sub(r':$','',parameter)})
continue
key_and_value = parameter.split('=')
devices[-1].update({
key_and_value[0]: re.sub(r'"','',key_and_value[1])
})

uuids = [{dev['DEVICE']: dev['UUID']} for dev in devices if 'UUID' in dev.keys()]
print(json.dumps(uuids, indent=4, sort_keys=True))

虽然,这可能是矫枉过正,并且此脚本 XD 中缺少相当多的错误处理/优化

我假设您正在 initramfs 中使用 busybox,并且您正在等待带有 rootfs 的 USB 驱动器可用。

您可以使用以下 awk 脚本(busybox awk 兼容)。

# cat get-ruuid.awk 
BEGIN {
ruuid=ENVIRON["RUUID"]
}
/^/dev/sd[a-z]/ {
if (index($0, tolower(ruuid)) || index($0, toupper(ruuid))) {
split($1, parts, ":")
printf("%sn", parts[1])
exit(0) # Return success and stop further scanning.
}
}
END {
exit(1) # If we reach the end, it means RUUID was not found.
}

从例如 init 脚本中调用它;这不是最理想的方式。

# The UUID of your root partition
export RUUID="<put proper uuid value here>"
for x in 1, 2, 3, 4, 5 ; do
mdev -s
found=$(blkid | awk -f ./get-ruuid.awk)
test -z $found || break; # If no longer zero length, break the loop.
sleep 1
done

但是,如果这是您想要拥有一个initramfs的唯一原因,我会使用"root=PARTUUID=...waitroot' Linux 内核命令行选项。检查内核文档和源代码。

使用 blkid 命令获取根分区的正确 PARTUUID(不是 UUID)。

最新更新