我正在尝试编写一个shell脚本,在其中我必须在字符串中查找 -32 的存在。不幸的是,我不必使用任何bashisms,因为它必须在运行Dash的计算机上运行。
我试过了case ${1+"$@"} in *-32*);;
,但是会选择 -321 之类的东西。有没有办法使用正则表达式或其他东西来寻找那个标志?它周围可以有其他标志,用字符串中的空格分隔。
我认为我需要的正则表达式用后面的空格或行尾来查找-32。 -32(\s|$)
我对正则表达式很陌生,所以我不确定这是否是最好的方法。任何帮助将不胜感激!
谢谢!
答案 0 :(得分:3)
您可以将grep
与字边界结合使用:
grep -E '-32\b' FILE
\b
匹配'字边界'=字母数字字符和非字母数字字符之间的位置。
在默认语言环境中,“字母数字字符”(如上面使用的术语)表示与字符类[a-zA-Z0-9_]
匹配的任何字符(即任何数字,任何字母A-Z和下划线) )。
以类似的方式\B
匹配不字边界的任何地方(即任何一侧的字符属于同一类型的任何位置,或两个字母数字字符,或两者都是非字母数字的。)
因此,如果您想确保减号必须在之前由非字母数字字符(例如空格),您还可以编写以下内容:
grep -E '\B-32\b' FILE
这将匹配xx -32 xx
(减号前的空格)但不 xx-32 xx
(没有空格)。由于空格和减号都是非字母数字\B
,它们之间会匹配,但\b
则不会。
如果您想确保减号前面有一个字母数字字符,您可以写下以下内容:
grep -E '\b-32\b' FILE
哪个匹配,例如x-32 x
(没有空格),但不是x -32 x
(在减号前有空格)。
答案 1 :(得分:1)
所有这些示例仅使用 内置函数,并且与dash
完全兼容。
如果您实际上在寻找字符串的子字符串,可以使用case
或if
。
让我通过使用每个函数编写两个不同的match
函数来说明。如果你很懒,你可以将这些函数中的任何一个剪切/粘贴到你的脚本中并使用:
if match -32 "$STRING"; then
echo "found '-32'!"
fi
E.g。如果你想在开头和结尾搜索$SUBSTR
,并用空格与字符串的其余部分分开,你可以使用这样的东西:
function match() {
local SUBSTR="$1" STR="$2" # get args
case " $STR " in # add extra spaces
*" $SUBSTR "*) return 0 ;; # return true if match
esac
return 1 # no match: return false
}
(在上面的函数中,我在$STR
周围添加空格,所以我不必在字符串的开头和结尾显式查找匹配项。)
function match() {
local SUBSTR=" $1 " STR=" $2 " # get args + add extra spaces
[ "${STR#*"$SUBSTR"}" != "$STR" ] \
&& return 0 # match: return true
return 1 # no match: return false
}
这个if
声明有点棘手。表达式${STR#*"$SUBSTR"}
表示$STR
,并从中删除所有内容,直至第一次出现$SUBSTR
(如果找不到$SUBSTR
,不要删除任何东西)。然后我们将其与原始$STR
进行比较,如果它们不相同,我们就知道找到了子字符串。
现在,如果您实际上正在寻找一个参数,您可以使用上述任何函数,然后只使用match "-32" "$*"
,但会找到所有子字符串,而不是将参数彼此区分(例如在不太可能的情况下,任何参数(如文件名)都发生在包含字符串'-32'以匹配)。
在这种情况下,最好只看一下args。我再次为你写一个小功能,你可以用argmatch "$ARG" "$@"
argmatch() {
local FIND="$1" ARG; shift # get $FIND arg, remove it from $@
for ARG; do # loop $@
[ "$ARG" = "$FIND" ] && return 0 # found? then return true
done
return 1 # return false
}