2

I want to grep file A for every phrase in file B, where a phrase is a string of words of length X. Ideally, it would be an approximate grep, like agrep. Is there a way to do that using command-line tools?

5
  • 4
    grep has -f option which allows you to use patterns from a file, with one pattern per line. Can't really tell from your question if that works for you. – Munir Feb 26 '16 at 16:47
  • It sounds like you may just want to diff the files – Centimane Feb 26 '16 at 16:52
  • agrep: approximate matching is not supported with -f option – Stéphane Chazelas Feb 26 '16 at 17:07
  • @Dave, is there a way to run diff to only show similarities, not differences? – Jonathan Feb 26 '16 at 17:11
  • @Jon using the line-formatting options it is: diff file1 file2 --old-line-format='' --new-line-format='' --unchanged-line-format='%L' I'll make an answer to explain it too – Centimane Feb 26 '16 at 17:50
2

With zsh, you could try something like:

x=3
B_words=($(<B))
A_words=($(<A))
A="$A_words"

setopt extendedglob
for ((i = 1; i<=$#B_words - x + 1; i++)) {
  phrase=$B_words[i,i+x-1]
  [[ " $A " = (#a2)*" $phrase "* ]] && printf '%s\n' $phrase
}

Which should give you the sequences of 3 words of file B that are also found in file A (allowing 2 errors with (#a2)).

For instance, if A is your question and B is the sentence above, I get:

of 3 words
3 words of
in file A

Or if you want to see what was matched in file A:

for ((i = 1; i<=$#B_words - x + 1; i++)) {
  phrase=$B_words[i,i+x-1]
  [[ " $A " = (#a2)(#b)*" "($phrase)" "* ]] &&
    printf '%s\n' "$phrase ($match[1])"
}

which gives:

of 3 words (of words)
3 words of (words of)
in file A (in file B,)

words here are defined as sequences of non-IFS characters which with the default value of $IFS is any character other than space, tab, newline and nul.

0

You can use diff so long as you're concerned with whole lines:

diff file1 file2 --old-line-format='' --new-line-format='' --unchanged-line-format='%L'

The old-line-format refers to lines only in the first file, the format is blank to leave them out.

The new-line-format refers to lines only in the second file, the format is blank to leave them out.

The unchanged-line-format refers to lines in both files, and the format '%L' is to print out the line including its line break.

You can see more about the formatting of diff output here: http://www.gnu.org/software/diffutils/manual/html_node/Line-Formats.html

-1

Easy, just run cat A | grep -f B for patterna or simple bash script:

#!/bin/bash

IFS=' ' read -ra ADDR <<< $(cat "$1")

read -ra ADDR2 <<< $(cat "$2")

for i in "${ADDR[@]}"; do

    for n in "${ADDR2[@]}"; do

    if [[ "$i" -eq "$n" ]]; then

        echo $n

    fi

    done

done

and run it with files as parameters ./scritp.sh A B

3
  • As @munircontractor is saying above, grep -f takes file of patterns, with one pattern per line. But my file B doesn't have one pattern per line--it's just a regular text file (a book), and so a phrase can appear anywhere in the line. – Jonathan Feb 26 '16 at 17:04
  • Unfortunately, grep doesn't do approximate matching and agrep supports -f but then can't do approximate matching. Its regexp support is also quite limited so that using agrep 'foo|bar|...longregexp' is generally not an option. – Stéphane Chazelas Feb 26 '16 at 17:12
  • added a script solution for space separated words. if u use different separator - change the IFS value to match it. – Ivan Temchenko Feb 26 '16 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.