Como saber se um arquivo de texto é um subconjunto de outro

10

Estou tentando encontrar uma maneira de prever se um arquivo de texto é um subconjunto de outro.

Por exemplo:

foo
bar

é um subconjunto de

foo
bar
pluto

Enquanto:

foo
pluto

e

foo
bar

não são um subconjunto um do outro ..

Existe uma maneira de prever isso automaticamente?

Esta verificação deve ser uma verificação cruzada e deve retornar:

file1 subset of file2 :    True
file2 subset of file1 :    True
otherwise             :    False
    
por gc5 12.02.2014 / 13:36

5 respostas

10

Se o conteúdo desses arquivos for chamado de file1 , file2 e file3 em ordem de aparecimento, você poderá fazê-lo com o seguinte one-liner:

 # python -c "x=open('file1').read(); y=open('file2').read(); print x in y or y in x"
 True
 # python -c "x=open('file2').read(); y=open('file1').read(); print x in y or y in x"
 True
 # python -c "x=open('file1').read(); y=open('file3').read(); print x in y or y in x"
 False
    
por 12.02.2014 / 14:03
2

Se f1 é um subconjunto de f2, então f1 - f2 é um conjunto vazio. Com base nisso, podemos escrever uma função is_subset e uma função derivada dela. De acordo com Defina a diferença entre dois arquivos de texto



sort_files () {
  f1_sorted="$1.sorted"
  f2_sorted="$2.sorted"

  if [ ! -f $f1_sorted ]; then
    cat $1 | sort | uniq > $f1_sorted
  fi

  if [ ! -f $f2_sorted ]; then
    cat $2 | sort | uniq > $f2_sorted
  fi
}

remove_sorted_files () {
  f1_sorted="$1.sorted"
  f2_sorted="$2.sorted"
  rm -f $f1_sorted
  rm -f $f2_sorted
}

set_union () {
  sort_files $1 $2
  cat "$1.sorted" "$2.sorted" | sort | uniq
  remove_sorted_files $1 $2
}

set_diff () {
  sort_files $1 $2
  cat "$1.sorted" "$2.sorted" "$2.sorted" | sort | uniq -u
  remove_sorted_files $1 $2
}

rset_diff () {
  sort_files $1 $2
  cat "$1.sorted" "$2.sorted" "$1.sorted" | sort | uniq -u
  remove_sorted_files $1 $2
}

is_subset () {
  sort_files $1 $2
  output=$(set_diff $1 $2)
  remove_sorted_files $1 $2

  if [ -z $output ]; then
    return 0
  else
    return 1
  fi

}

    
por 14.11.2014 / 09:36
1

Eu encontrei uma solução graças a esta pergunta

Basicamente, estou testando dois arquivos a.txt e b.txt com este script:

#!/bin/bash

first_cmp=$(diff --unchanged-line-format= --old-line-format= --new-line-format='%L' "$1" "$2" | wc -l)
second_cmp=$(diff --unchanged-line-format= --old-line-format= --new-line-format='%L' "$2" "$1" | wc -l)

if [ "$first_cmp" -eq "0" -o "$second_cmp" -eq "0" ]
then
    echo "Subset"
    exit 0
else
    echo "Not subset"
    exit 1
fi

Se um for um subconjunto do outro, o script retornará 0 para True caso contrário 1 .

    
por 12.02.2014 / 14:07
1

com perl :

if perl -0777 -e '$n = <>; $h = <>; exit(index($h,$n)<0)' needle.txt haystack.txt
then echo needle.txt is found in haystack.txt
fi
    
por 21.11.2017 / 16:43
0

De link :

Comm compares two sorted files line by line. It may be run in such a way that it outputs lines that appear only in the first specified file. If the first file is subset of the second, then all the lines in the 1st file also appear in the 2nd, so no output is produced:

$ comm -23 <(sort subset | uniq) <(sort set | uniq) | head -1
# comm returns no output if subset ⊆ set
# comm outputs something if subset ⊊ set
    
por 24.01.2018 / 16:56