检查字符串是否为UUID

16

我正在尝试测试字符串$uuid 是否为UUID。我已经编写了这个脚本,但由于某种原因它无法工作:

uuid="7632f5ab-4bac-11e6-bcb7-0cc47a6c4dbd"
if [[ $uuid =~ ^\{?[A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}\}?$ ]]; then
    echo "true"
else
    echo "false"
fi

你在正则表达式上犯了一个错误。请看我的新编辑答案。 - Spenser Truex
3个回答

17

您的正则表达式不接受小写字母作为有效字符。这是修复后的版本:

#!/bin/bash
uuid="7632f5ab-4bac-11e6-bcb7-0cc47a6c4dbd"
if [[ $uuid =~ ^\{?[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}\}?$ ]]; then
    echo "true"
else
    echo "false"
fi
首先,你只需要搜索A-F而不是A-Z,因为UUID包含十六进制数字。
请注意每个字符类中添加了a-f。你的版本将拒绝任何以小写形式打印的UUID。这个新版本现在对我来说很好用。另一个解决方案是仅使用大写UUID,而不是您拥有的小写UUID。 您的[A-Z0-9]类已被替换为[A-F0-9a-f],出于这些原因。
请查看Ekeyme Mo的帖子以了解安全考虑事项。

15

连字符并没有实际意义;UUID只是一个128位的值,传统的显示方式采用8-4-4-4-12的分组方式,但这不是必需的。这意味着只要你在去除-后保留32个十六进制数字,它就是一个UUID。

uuid="7632f5ab-4bac-11e6-bcb7-0cc47a6c4dbd"
if [[ ${uuid//-/} =~ ^[[:xdigit:]]{32}$ ]]; then
    echo "true"
else
    echo "false"
fi

可以用。引用${uuid//-/}可能是值得的,不是吗? - orzel
2
[[...]] 中,参数扩展不受单词拆分或路径名扩展的影响,这是引用它们的两个原因。 - chepner

5

在bash中,将模式预先保存到变量中使用=~子句更安全,以避免在bash中出现不可预测的转义。

uuid="7632f5ab-4bac-11e6-bcb7-0cc47a6c4dbd"
pattern='^\{?[A-Z0-9a-z]{8}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{12}\}?$'

if [[ "$uuid" =~ $pattern ]]; then
    echo "true" 
else
    echo "false" 
fi

3
“更加安全”可以简化为“更安全”(一个语法细节)。但是通常情况下,当使用 $pattern 时,不管怎样都会进行转义,例如在反引号内使用它。无论如何,为 $uuid 添加引号总是一个好习惯,以确保变量的安全。 - grochmal
如果我执行这个脚本,它会返回“false”。我在Linux上使用的是bash 4.3.46。 - orzel
正常情况下,第一个和最后一个 { 必须被转义,我已经编辑过了。 - kyodev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接