regex 如何在bash中检查字符串是否为-key value格式?

guicsvcw  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(98)

我想验证一个必须是-key1 value1 -key2 value2的字符串。
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"

你能给予我一些建议吗?

lymnna71

lymnna711#

有一个很好的机会,你的起始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 "$@",然后去掉第一个循环。

jdzmm42g

jdzmm42g2#

我将遍历字符串并检查每个键值对,它使用修改后的正则表达式-([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
2ledvvac

2ledvvac3#

您可以使用

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_]+)?)*-零次或多次出现空格+与上面相同的模式
  • $-字符串结束。

相关问题