有没有办法完成此不使用使用sed
,grep
,awk
或[[ ]]
构造等外部程序,而不使用嵌套循环?
基本上,我想循环提供的参数(单词)并检查它是否在字符串中。
我说的是实际的令牌(IFS分隔的字符串)。
因此,在字符串word1 word2 word3 word4
我能想到的唯一蹩脚的解决方案是:
string="word1 word2 word3 word4"
# attempt to remove diff combos of
# space + word
for i in $@; do
[ "${string/ $i / }" == "$string" ] &&
[ "${string/#$i / }" == "$string" ] &&
[ "${string/% $i/ }" == "$string" ] &&
echo "$i not found" && continue
# if found, actually remove
# again attempting diff combos
string="${string/ $i / }"
string="${string/#$i / }"
string="${string/% $i/ }"
done
echo "$string"
这应该给出:
~$ ./script word1 word3 word5
word5 not found
word2 word4
答案 0 :(得分:1)
您始终可以使用传统的expr
语法。例如expr $string : $regex
。例如,使用您的输入(并稍微重新格式化),您可以执行以下操作:
#!/bin/bash --norc
string="word1 word2 word3 word4"
for i in $@; do
if [ $(expr "$string" : ".*$i.*") -gt 0 ]; then
printf "'%s' found in '%s'\n" "$i" "$string"
else
printf "'%s' NOT found in '%s'\n" "$i" "$string"
fi
done
<强>输出强>
$ bash srchwordexpr.sh word1 word3 word5
'word1' found in 'word1 word2 word3 word4'
'word3' found in 'word1 word2 word3 word4'
'word5' NOT found in 'word1 word2 word3 word4'
expr
不是您排除的工具之一,无论您认为它属于该群组,请告诉我。
您还可以使用相同结果的简单子字符串删除:
if [ "$string" != "${string/$i}" ]; then
答案 1 :(得分:1)
现代 Bash
$ a="qqq www eee rrr"
$ eval typeset -A t=( $(printf '[%s]=1 ' $a) )
$ w=www
$ [ "${t[$w]}" ] && echo yes || echo no
yes
$ w=oops
$ [ "${t[$w]}" ] && echo yes || echo no
no
即使这里没有明显的循环,内部也必然有循环(t[]数组的加载),然后通过散列查找单词。
这里没有 fork/exec 因为 printf 是内置的,当不再需要 t[] 时,取消它。
这个答案来晚了 :) 我把它记录下来。
答案 2 :(得分:0)
#!/bin/bash
string="word1 word2 word3 word4"
# Usage: inarray "$value" "${array[@]}"
inarray() { local n=$1 h; shift; for h; do [ "$n" == "$h" ] && return; done; return 1; }
read -ra arr <<< "$string"
for arg; do
if inarray "$arg" "${arr[@]}"; then
printf '%s FOUND in "%s"\n' "$arg" "$string"
else
printf '%s NOT FOUND in "%s"\n' "$arg" "$string"
fi
done
用法示例:
(脚本名称为sof
)
./sof word1 wor word3 "word4 "
word1 FOUND in "word1 word2 word3 word4"
wor NOT FOUND in "word1 word2 word3 word4"
word3 FOUND in "word1 word2 word3 word4"
word4 NOT FOUND in "word1 word2 word3 word4"
修改强> 我注意到OP请求不使用嵌套循环,这个答案就是这样。 因此它没有回答这个问题。我将在这里留下答案,以防将来有人将从中受益,除非我被要求删除它。
答案 3 :(得分:0)
使用中间数组:
#!/bin/bash
string="word1 word2 word3 word4"
array=($string)
for i in "$@"; do
found=false
for j in "${!array[@]}"; do
if [[ $i == ${array[$j]} ]]; then
unset array[$j]
found=true
break
fi
done
"$found" || echo "$i not found" >&2
done
echo "${array[@]}"
结果正好是您要的:
$ ./script word1 word3 word5
word5 not found
word2 word4