提问人:ikhvjs 提问时间:9/11/2023 最后编辑:ikhvjs 更新时间:9/12/2023 访问量:108
如何在bash中检查字符串是否为-key值格式?
How to check if the string is in -key value format in bash?
问:
我想验证一个字符串,该字符串的格式必须为 。-key1 value1 -key2 value2
允许大写/小写字符、数字和下划线。like 或key
-key_1
-Key_name_2
可以是任何字符串,但不能是空字符串。所以,可能是 , .此外,可以使用双引号,我们从双引号中提取值。value
value
value1
-value1
value
"value1WithQuote"
value1WithQuote
键值对的数量最多可以是 10 对。
我尝试使用下面的正则表达式,但它只检查第一个键
str="-mykey1 keyvalue1 -MY_KEY_2 keyvalue2"
regex="-([a-zA-Z]+)"
[[ $str =~ $regex ]] && echo "matched"
你能给我一些建议吗?
答:
1赞
Freeman
9/11/2023
#1
我将遍历字符串并检查每个键值对,它使用修改后的正则表达式,其中匹配键并匹配值,循环继续,直到在字符串中找不到更多的键值对。-([a-zA-Z_0-9]+) ([^ ]+)
([a-zA-Z_0-9]+)
([^ ]+)
while
看看这个
str="-mykey1 keyvalue1 -MY_KEY_2 keyvalue2"
regex="-([a-zA-Z_0-9]+) ([^ ]+)"
while [[ $str =~ $regex ]]; do
key="${BASH_REMATCH[1]}"
value="${BASH_REMATCH[2]}"
echo "Key: $key, Value: $value"
str="${str/${BASH_REMATCH[0]}/}"
done
更新
按照您的要求,我将从字符串中提取键值对并将它们存储在关联数组中(),我还对重复键、空值和键值对的最大数量进行额外检查,最后,它会打印提取的键值对!keyValuePairs
str="-mykey1 keyvalue1 -MY_KEY_2 keyvalue2"
#regex pattern for key-value pairs
regex="-([a-zA-Z0-9_]+)\s+([^-\s]+)"
#array to store the extracted key-value pairs
declare -A keyValuePairs
#iterate through the string and extract key-value pairs
while [[ $str =~ $regex ]]; do
key="${BASH_REMATCH[1]}"
value="${BASH_REMATCH[2]}"
#checking if the key already exists
if [[ ${keyValuePairs[$key]+_} ]]; then
echo "Duplicate key: $key"
exit 1
fi
#checking if the value is empty
if [[ -z $value ]]; then
echo "Empty value for key: $key"
exit 1
fi
#storing the key-value pair in the array
keyValuePairs[$key]=$value
#removing the matched key-value pair from the string
str=${str/${BASH_REMATCH[0]}/}
done
#checking the number of key-value pairs
numPairs=${#keyValuePairs[@]}
if (( numPairs > 10 )); then
echo "Too many key-value pairs. Maximum is 10."
exit 1
fi
#printing the extracted key-value pairs
for key in "${!keyValuePairs[@]}"; do
value="${keyValuePairs[$key]}"
echo "Key: $key, Value: $value"
done
评论
1赞
ikhvjs
9/11/2023
谢谢。我更新了我的任务以提到值不能是空字符串。你也能处理这种情况吗?所以 value 也可以是 “-value1”
1赞
Wiktor Stribiżew
9/11/2023
#2
你可以使用
str="-mykey1 keyvalue1 -MY_KEY_2 keyvalue2"
regex='^-[a-zA-Z0-9_]+( [a-zA-Z0-9]+)?( -[a-zA-Z0-9_]+( [a-zA-Z0-9_]+)?){0,9}$'
[[ $str =~ $regex ]] && echo "matched"
细节:
^
- 字符串的开头-
- 连字符[a-zA-Z0-9_]+
- 一个或多个字母/数字/下划线( [a-zA-Z0-9]+)?
- 可选出现以下情况:[a-zA-Z0-9]+
- 一个或多个字母/数字
( -[a-zA-Z0-9_]+( [a-zA-Z0-9_]+)?)*
- 空格出现次数为零次或多次 + 与上述相同的模式$
- 字符串末尾。
评论
0赞
ikhvjs
9/11/2023
谢谢。我更新了我的问题。键值对的数量最多可以是 10 对。因此,value 不能是空字符串,它可以是“-value1”
0赞
Wiktor Stribiżew
9/11/2023
@ikhvjs 只需将零件设置为可选,即 并将最后一个替换为设置附加选项数量的限制。<space>[a-zA-Z0-9_]+
( [a-zA-Z0-9_]+)?
*
{0,9}
1赞
Ed Morton
9/11/2023
#3
很有可能你的起始值实际上应该被填充为数组而不是字符串,但如果你的值都不能包含空格,这里是如何将其转换为数组并立即使用它:str
$ cat tst.sh
#!/usr/bin/env bash
str="-mykey1 keyvalue1 -MY_KEY_2 keyvalue2 -this:that"
read -r -a arr <<<"$str"
regex='^-[[:alnum:]_]+$'
for (( i=0; i<${#arr[@]}; i+=2 )); do
key="${arr[i]}"
val="${arr[((i+1))]}"
if [[ $key =~ $regex ]]; then
echo "Key \"$key\" matched"
else
echo "Key \"$key\" did not match"
fi
if [[ -n $val ]]; then
echo "Val \"$val\" is non-empty"
else
echo "Val \"$val\" is empty"
fi
done
$ ./tst.sh
Key "-mykey1" matched
Val "keyvalue1" is non-empty
Key "-MY_KEY_2" matched
Val "keyvalue2" is non-empty
Key "-this:that" did not match
Val "" is empty
如前所述,上面假设您的值都不包含空格,否则以这种方式填充数组将失败。
编辑:说明为什么你应该将参数存储在数组而不是字符串中:
$ cat tst.sh
#!/usr/bin/env bash
args=()
for i in "$@"; do
args+=( "$i" )
done
for (( i=0; i<${#args[@]}; i++ )); do
printf 'Argument #%d = "%s"\n' "$i" "${args[i]}"
done
$ ./tst.sh -key1 'this -foo that' -key2 value2
Argument #0 = "-key1"
Argument #1 = "this -foo that"
Argument #2 = "-key2"
Argument #3 = "value2"
第一个循环是将参数值存储在数组中,第二个循环是访问它们的值。
我假设您有理由希望存储参数值,否则您可以在上面的第二个循环中执行并删除第一个循环。for arg in "$@"
评论
regex='^-[a-zA-Z]+([[:blank:]]-[a-zA-Z]+)*$'
-MY_KEY_2 keyvalye2