No *_*ion 8 shell string function pattern-matching
我想编写一个函数来检查给定的变量,例如,var以给定字符串列表中的任何单词开头。这个列表不会改变。
为了实例化,让我们假设我想检查是否var以aa,abc或开头3@3。
此外,我想检查是否var包含字符>.
假设这个函数被调用check_func。我的预期用途看起来像
if check_func "$var"; then
do stuff
fi
Run Code Online (Sandbox Code Playgroud)
例如,应该“做的东西”了
aardvark,abcdef,3@3com.com和12>5。
我已经看到这个 SO 问题,其中用户提供了部分工作:
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
Run Code Online (Sandbox Code Playgroud)
我的想法是我会遍历上面提到的列表并使用这个函数。我的困难在于不完全理解应该如何退出(或任何替代返回)来完成这项工作。
Kus*_*nda 11
check_prefixes () {
value=$1
for prefix in aa abc 3@3; do
case $value in
"$prefix"*) return 0
esac
done
return 1
}
check_contains_gt () {
value=$1
case $value in
*">"*) return 0
esac
return 1
}
var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
printf '"%s" contains ">" and starts with one of the prefixes\n' "$var"
fi
Run Code Online (Sandbox Code Playgroud)
我将测试分为两个功能。case ... esac一旦可以确定,两者都使用并返回成功(零)。如果没有匹配项,则返回失败 (1)。
为了使前缀列表更像一个动态列表,可以将第一个函数写为
check_prefixes () {
value=$1
shift
for prefix do
case $value in
"$prefix"*) return 0
esac
done
return 1
}
Run Code Online (Sandbox Code Playgroud)
(要检查的值是第一个参数,我们将其保存在函数的参数列表中value,然后shift从参数列表中删除;然后我们遍历剩余的参数),然后将其调用为
check_prefixes "$var" aa abc 3@3
Run Code Online (Sandbox Code Playgroud)
第二个函数可以以类似的方式更改为
check_prefixes "$var" aa abc 3@3
Run Code Online (Sandbox Code Playgroud)
(检查某些任意子字符串),或
check_contains () {
value=$1
shift
case $value in
*"$1"*) return 0
esac
return 1
}
Run Code Online (Sandbox Code Playgroud)
(检查多个子字符串中的任何一个)
使用正则表达式的,你可以写的属性start与^和contain通过什么。
要检查的以或开头和包含的正则表达式列表是:aa abc3@3 >
^aa ^abc ^3@3 >
Run Code Online (Sandbox Code Playgroud)
使其成为正确引用的列表并要求 bash 使用正则表达式 ( =~):
check_func() {
matched=1
for test_regex in '^aa' '^abc' '^3@3' '>'; do
if [[ $var =~ $test_regex ]] ; then
matched=0
break
fi
done
return "$matched"
}
var='aaIsAMatch'
if check_func; then
echo "A match was found"
fi
Run Code Online (Sandbox Code Playgroud)
该函数对匹配列表和变量名称进行了硬编码。
给出数组变量中的正则表达式列表和要测试的第一个参数的值:
check_func() {
local matched; matched=1
for t in "${test_regex[@]}"; do
[[ $1 =~ $t ]] && { matched=0; break; }
done
return "$matched"
}
test_regex=('^aa' '^abc' '^3@3' '>')
if check_func 'aaIsAMatch'; then
echo "A match was found"
fi
Run Code Online (Sandbox Code Playgroud)
该函数可以进一步改进以使用变量的名称(而不是值)作为第一个参数。
由于 posix shell 中没有正则表达式,并且测试的唯一方法是 case 语句,因此我们必须使用 case 语句。遗憾的是,对于较旧的 shell([没有可用的扩展 globs][1]),我们必须循环进行所有测试。而且,球体需要是:
'aa*' 'abc*' '3@3*' '*>*'
Run Code Online (Sandbox Code Playgroud)
针对多个 glob 测试多个输入字符串的脚本示例:
check_func() { :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; #break;; esac
echo "matched $value with $t"
;;
esac
done
return "$matched"
}
for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
echo "========A match was found for \"$var\""
fi
done
Run Code Online (Sandbox Code Playgroud)
与您的请求完全匹配的函数的更简单版本:
check_func() { :
matched=1
value=$1; shift
for t in "$@"; do
case $value in $t) matched=0; break;; esac
done
return "$matched"
}
Run Code Online (Sandbox Code Playgroud)