简体   繁体   English

Bash:在字符串中查找单词

[英]Bash: Find word in string

Is there any way to accomplish this without using external programs like sed , grep , awk or the [[ ]] construct and without using nested loops?有没有办法在使用外部程序(如sedgrepawk[[ ]]构造和不使用嵌套循环的情况下)来实现这一点?

Basically, I would like to loop over the provided arguments(words) and check whether it's in the string.基本上,我想遍历提供的参数(单词)并检查它是否在字符串中。

By word, I mean actual tokens (IFS separated strings).按词,我的意思是实际令牌(IFS 分隔的字符串)。

So, find word3 in string word1 word2 word3 word4所以,在字符串word1 word2 word3 word4找到 word3

The only crappy solution I could come up with is:我能想出的唯一糟糕的解决方案是:

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"

This should give:这应该给出:

~$ ./script word1 word3 word5

word5 not found
word2 word4

You can always use the traditional expr syntax.您始终可以使用传统的expr语法。 eg expr $string : $regex .例如expr $string : $regex For example, using your input (and reformatting slightly), you could do:例如,使用您的输入(并稍微重新格式化),您可以执行以下操作:

#!/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

Output输出

$ 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 is not one of your excluded tools, whether you consider it to belong in that group, let me know. expr不是您排除的工具之一,无论您是否认为它属于该组,请告诉我。

You can also use a simple substring removal with the same results:您还可以使用具有相同结果的简单子字符串删除:

if [ "$string" != "${string/$i}" ]; then

Modern Bash现代 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

Even though there is no apparent loop here, there is necessarilly one internally (the loading of the t[] array), then looking for a word is done by hashing.即使这里没有明显的循环,内部也必须有一个(t[] 数组的加载),然后通过散列来查找单词。

There is no fork/exec since printf is a builtin here, when t[] is not needed anymore, unset it.没有 fork/exec 因为 printf 在这里是内置的,当不再需要 t[] 时,取消它。

This answer is late :) I give it for the record.这个答案来晚了:) 我把它记录下来。

#!/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

Usage example: ( Script name is sof )用法示例:(脚本名称为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"

EDIT I noticed that the OP requested to not use nested loops, which this answer does.编辑我注意到 OP 要求不使用嵌套循环,这个答案就是这样做的。 Therefore it does not answers the question.I'll leave the answer here in case that someone will benefit from it in the future, unless I'll be requested to remove it.因此,它没有回答问题。我会在这里留下答案,以防将来有人会从中受益,除非我被要求将其删除。

Use an intermediate array:使用中间数组:

#!/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[@]}"

The result is exactly what you were asking for:结果正是您所要求的:

$ ./script word1 word3 word5
word5 not found
word2 word4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM