查找包含另一个文件中所有单词/行的所有文件

时间:2014-07-29 00:41:45

标签: linux bash awk sed grep

我要出去说这是一个家庭作业的问题,但我觉得我已经筋疲力尽地在网上搜索任何与如何解决这个问题有关的事情,或者我只是没有正确地为Google写字/计算器。

问题的开头是这样的:文件 包含单词列表。每个单词都在一个单独的行上。文件 story1,story2,...,story100 是短篇小说。

这是一个多部分的问题,但最后一部分让我感到困惑:找出包含文件 字词中所有单词的故事文件。

之前有一个问题类似:找出文件 中至少包含一个单词的故事文件(打印文件名)。

这是我用grep解决的:

grep -l -f words story*

我的印象是我还必须使用grep来解决最后一个问题,但我似乎找不到grep的选项或任何只能返回匹配模式文件中所有内容的文件的选项。看来我可能不得不用shell脚本做这个,但不确定从哪里开始,或者我是否需要grep。有关如何解决这个问题的任何指示?

谢谢!

修改

这些是教师给我们的解决方案的正确答案。

主要问题之前的问题: grep -l -f words story*

主要问题:

for story in `ls story*`
do
    (( match = 0 ))

    for word in `cat words`
    do
        if [ `grep -l $word $story` ]
        then
            (( match++ ))
        else
            break
        fi
    done

    if [ $match -eq `wc -w < words` ]
    then
        echo $story
    fi
done

感谢大家提供了深思熟虑的意见和答案,对不起,我有点迟到了。

5 个答案:

答案 0 :(得分:1)

蛮力方法可能不是最快的方法,但只要你没有10万多个单词和故事,那就没事了。基本上,您将只使用grep测试每个文件包含每个单词,一次一个。如果grep未能在故事中找到该单词,请转到下一个故事。如果在故事中找到所有单词,则将故事添加到goodstories数组中。最后,打印所有的故事:

#!/bin/bash

declare -a words        # array containing all words
declare -a goodstories  # array contianing stories with all words

words=( `< /path/to/words` )    # fill words array

## for each stories file (assumed they exist in dir of their own)
for s in `find /path/to/stories/base/dir -type f` ; do

    wfound=0                    # all words found flag initialized to 'true'

    ## for each word in words
    for w in ${words[@]}; do

        ## test that word is in story, if not set wfound=1 break
        grep -q $w $s &>/dev/null || {

            wfound=1
            break

        }

    done

    ## if grep found all words, add story to goodstories array
    test "$wfound" -eq 0 && goodstories+=( $s )

done

## output your list of goodstories

if test "${#goodstories[@]}" -gt 0 ; then

    echo -e "\nStories that contained all words:\n"
    for s in ${goodstories[@]}; do

        echo "  $s"

    done

else

    echo "No stories contained all words"

fi

exit 0

注意:我没有创建单词或故事文件,因此如果您发现拼写错误等,请将代码视为伪代码。然而,它并没有被打到一起......

答案 1 :(得分:1)

假设您的单词文件不包含用于\<...\>工作边界的GNU awk的RE元字符:

列出包含一个单词的文件:

awk '
NR==FNR { words["\\<" $0 "\\>"]; next }
{
    for (word in words) {
        if ($0 ~ word) {
            print FILENAME
            next
        }
    }
}
' words story*

列出包含所有单词的文件(另外ENDFILE,删除(数组)和长度(数组)的GNU awk):

awk '
NR==FNR { words["\\<" $0 "\\>"]; next }
{
    for (word in words) {
        if ($0 ~ word) {
            found[word]
        }
    }
}
ENDFILE {
    if ( length(found) == length(words) ) {
        print FILENAME
    }
    delete found
}
' words story*

答案 2 :(得分:0)

for EachFile in story*
 do
    sed 's/  */\
/g' ${EachFile} | sort -u > /tmp/StoryInList
    if [ $( fgrep -w -c -v -f /tmp/StoryInList words ) -eq 0 ]
     then
       echo ${EachFile}
     fi
 done
rm /tmp/StoryInList

批处理中的一些代码,但即使使用grep强度

数千个单词也可以完成工作

答案 3 :(得分:0)

如果您要搜索唯一字词列表,并且每个故事都包含唯一字词列表,则使用{{1}更容易解决问题}}:

fgrep -c

答案 4 :(得分:0)

# wcheck: finds story* files that contain all words in words file

# for each file named story... (in this directory)
for file in story*
do
    stGood=0  # story is intialized as containing words or true

    ## for each word in the words file
    for word in $(cat words) ; do

        ## if test using grep exit status for existance of word
        if ! grep -q -F $word $file
        then
            stGood=1 #if word is not found story is set to false
            break
        fi   
    done
    ## if story is still true then filename is printed
    if [ $stGood == 0 ]
        then
        echo $file
    fi
done
exit