Bash:在字符串中查找单词

时间:2016-03-09 13:27:17

标签: bash

有没有办法完成此不使用使用sedgrepawk[[ ]]构造等外部程序,而不使用嵌套循环?

基本上,我想循环提供的参数(单词)并检查它是否在字符串中。

我说的是实际的令牌(IFS分隔的字符串)。

因此,在字符串word1 word2 word3 word4

中找到word3

我能想到的唯一蹩脚的解决方案是:

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

4 个答案:

答案 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