Я думаю, что мы определили, что некоторые промежуточные серверы кэширования (, например, сервер в моем домашнем маршрутизаторе ), неохотно возвращают RFC1918 («частные» )адреса. Таким образом, короткие запросы, которые выполняет большинство программ (браузеры и т. д. ), будут использовать эти кеши, но сервер возвращает количество «не найдено». Таким образом, локальный сервер systemd
кэширует запись NODATA
, потому что считает, что это правильно.
Запрос ANY
не кэшируется промежуточными серверами, поэтому локальный сервер получает ответ от авторитетного сервера.
Или что-то в этом роде. Я пока оставлю вопрос без ответа на тот случай, если кто-то, кто действительно знает, как эти вещи работают, сможет лучше объяснить.
Гораздо более эффективный ответ, не использующий grep:
build_k_mers() {
k="$1"
slot="$2"
perl -ne 'for $n (0..(length $_)-'"$k"') {
$prefix = substr($_,$n,2);
$fh{$prefix} or open $fh{$prefix}, ">>", "tmp/kmer.$prefix.'"$slot"'";
$fh = $fh{$prefix};
print $fh substr($_,$n,'"$k"'),"\n"
}'
}
export -f build_k_mers
rm -rf tmp
mkdir tmp
export LC_ALL=C
# search strings must be sorted for comm
parsort patterns.txt | awk '{print >>"tmp/patterns."substr($1,1,2)}' &
# make shorter lines: Insert \n(last 12 char before \n) for every 32k
# This makes it easier for --pipepart to find a newline
# It will not change the kmers generated
perl -pe 's/(.{32000})(.{12})/$1$2\n$2/g' large_strings.txt > large_lines.txt
# Build 12-mers
parallel --pipepart --block -1 -a large_lines.txt 'build_k_mers 12 {%}'
# -j10 and 20s may be adjusted depending on hardware
parallel -j10 --delay 20s 'parsort -u tmp/kmer.{}.* > tmp/kmer.{}; rm tmp/kmer.{}.*' ::: `perl -e 'map { printf "%02x ",$_ } 0..255'`
wait
parallel comm -23 {} {=s/patterns./kmer./=} ::: tmp/patterns.??
Я протестировал это на полной работе(patterns.txt
:9 ГБ/725937231 строк,large_strings.txt
:19 ГБ/184 строки )и на моей 64-ядерной -машине это завершилось за 3 часа.
Это должно работать:
parallel --pipepart --block -1 -a large_strings.txt grep -oFf patterns.txt |
grep -vFf - patterns.txt > unmatched_patterns.txt
Если у вас есть ripgrep
, используйте:
parallel --pipepart --block -1 -a large_strings.txt rg -oFf patterns.txt |
rg -vFf - patterns.txt > unmatched_patterns.txt
Если patterns.txt
тоже огромен, взгляните на:
https://www.gnu.org/software/parallel/man.html#EXAMPLE:-Grepping-n-lines-for-m-regular-expressions
Ваша ситуация также довольно близка к проблеме, которую решает BLAT, за исключением того, что BLAT построен для ДНК. Но я не вижу, чтобы вы не могли использовать BLAT для вашей ситуации -возможно, с некоторыми изменениями (ну, вы могли бы преобразовать каждое шестнадцатеричное значение в 2 буквы ДНК и использовать их напрямую ). BLAT так же быстр, как поиск в базе данных, поэтому нет никакого сравнения с grep
.http://genome.ucsc.edu/FAQ/FAQblat.html#blat3
Не знаю, сработает ли это...
while read line;
do
grep -oF "$line" large_strings.txt &
done <patterns.txt | grep -vFf - patterns.txt > unmatched_patterns.txt