Я хочу знать это, сколько раз 'ABCD' (файл A) прибывает в DB (файл B). Аналогично я хочу знать о каждой строке ожога, существующей в файле A против DB. Мне нужна автоматизированная команда, которая может упростить мою работу, потому что у меня есть большой объем данных в файле A, и я хочу искать его против многих баз данных. Я просто делаю символы полужирными для понимания.
ABCD
EFG
HIJKL
MNO
PQRSTU
XYZABCDFORNTUFPSRWSABCFYWSZCFTHBFORTYBJNFABCDDEFGACVRTEFGPQRMNOOPQEFGZXXXYY
ABCD 2
EFG 3
HIJKL 4567
MNO 0
PQRSTU 7652
Мое предложение:
IFS=; while read -r word; do printf "%s " $word; grep -o $word b | wc -l; done < a
while
мы циклично выполняемся в слова (файл a) printf "%s " $word
: печатает имя слова, например: ABCDgrep -o $word b | wc -l
: количества и печать количество случаев count_patterns.py
сценарий. Должно быть довольно хорошо для больших файлов. Использование OrderedDict
записывать все шаблоны из файла A, обеспеченного на командной строке и, ищет их в файле B.
#!/usr/bin/env python3
import sys
from collections import OrderedDict
with open(sys.argv[1]) as pattern_file, open(sys.argv[2]) as data_file:
patterns = OrderedDict.fromkeys(map(str.strip, pattern_file), 0)
for line in data_file:
for p in patterns:
patterns[p] += line.count(p)
for kv in patterns.items():
print(*kv)
Использование:
$ ./count_patterns.py file_A.txt file_B.txt
ABCD 4
EFG 3
HIJKL 0
MNO 1
PQRSTU 0
Это использует замену процесса от sed
который позволяет нам разделить файл A на новые строки в **
, и используйте grep -c
считать количество подобранных строк.
$ cat file_B.txt
ABCD**FORNTUFPSRWSABCFYWSZCFTHBFORTYBJNF**ABCD**D**EFG**ACVRT**EFG**PQRMNOOPQ**EFG**ZXXXYY
ABCD**FORNTUFPSRWSABCFYWSZCFTHBFORTYBJNF**ABCD
$ cat file_A.txt
ABCD
EFG
HIJKL
MNO
PQRSTU
$ while IFS= read -r pattern; do printf "%s\t" "$pattern"; grep -c "$pattern" < <( sed 's/\*\*/\n/g' file_B.txt ); done < file_A.txt
ABCD 4
EFG 3
HIJKL 0
MNO 1
PQRSTU 0
Не лучший способ сделать это, вероятно, не подходящий для больших файлов, но работ. Не рекомендовал бы использовать метод удара, но если набор данных не будет большим, то он будет работать.
Использование ассоциативных массивов Bash:
#!/bin/bash
set -eu
declare -A patterns
while IFS= read -r p; do
patterns["$p"]=0
done < "$1"
while IFS='*' read -ra l; do
for r in "${l[@]}"; do
if [ -n "$r" ] && [ -v patterns["$r"] ]; then
patterns[$r]=$((${patterns["$r"]} + 1))
fi
done
done < "$2"
for p in "${!patterns[@]}"; do
printf '%s\t%u\n' "$p" "${patterns["$p"]}"
done
Использование:
bash count-patterns.sh pattern-list.txt word-list.txt
Используя пользовательский класс словаря и функциональную обработку данных стиля:
#!/usr/bin/env python3
import sys, itertools, collections
class MyCounter(collections.UserDict):
def __init__(self, _dict):
self.data = _dict
def update(self, iterable):
for key in iterable:
self.data[key] += 1
with open(sys.argv[1]) as pattern_file:
patterns = MyCounter({ s.rstrip('\n'): 0 for s in pattern_file })
with open(sys.argv[2]) as wordlist_file:
patterns.update(filter(patterns.__contains__,
itertools.chain.from_iterable(map(
lambda s: s.rstrip('\n').split('**'), wordlist_file))))
for p in patterns.items():
print(*p, sep='\t')
Использование:
python3 count-patterns.py pattern-list.txt word-list.txt
#include <cstddef>
#include <utility>
#include <unordered_map>
#include <iostream>
#include <fstream>
namespace std
{
template <class Ch, class Tr, class K, class V, class H, class Eq>
basic_ostream<Ch,Tr> &operator<<( basic_ostream<Ch,Tr> &os,
const std::unordered_map<K,V,H,Eq> &m )
{
for (const typename std::unordered_map<K,V,H,Eq>::value_type &i: m)
os << i.first << '\t' << i.second << '\n';
return os.flush();
}
}
template <class Key, class Hash = std::hash<Key>, class Equal = std::equal_to<Key>>
class counter :
public std::unordered_map<Key, std::size_t, Hash, Equal>
{
private:
typedef std::unordered_map<Key, std::size_t, Hash, Equal> _base;
public:
void update_existing( const Key &k, std::size_t count = 1 )
{
const typename _base::iterator match = this->find(k);
if (match != this->end())
match->second += count;
}
};
int main( int argc, char *argv[] )
{
if (argc != 3)
{
std::cerr << "Usage: " << argv[0] << " <PATTERN-FILE> <WORDLIST-FILE>" << std::endl;
return 2;
}
counter<std::string> patterns;
std::string buf;
{
std::ifstream pattern_file(argv[1]);
while (pattern_file.good() && !std::getline(pattern_file, buf).fail())
patterns.emplace(std::move(buf), 0);
}
if (!patterns.empty())
{
std::ifstream wordlist_file(argv[2]);
while (wordlist_file.good() && !std::getline(wordlist_file, buf).fail())
{
static const char delim[] = {'*', '*'};
std::size_t offset = 0, p = 0;
while ((p = buf.find(delim, offset, sizeof(delim))) != std::string::npos)
{
patterns.update_existing(buf.substr(offset, p - offset));
offset = p + sizeof(delim);
}
patterns.update_existing(buf.erase(0, offset));
}
}
std::cout << patterns;
}
Скомпилируйте с:
c++ -std=c++11 -o count-patterns count-patterns.cpp
Использование:
./count-patterns pattern-list.txt word-list.txt
Вот awk
программа, которая должна сделать то, что Вы после:
BEGIN {FS="*"}
FNR==NR {a[$0]=0; next}
{for (i=1; i<=NF; i++) if ($i in a) a[$i]++}
END {
for (i in a) {
print i, a[i]
}
}
*
FNR==NR {a[$0]=0; next}
загружает слова для соответствия в массив a
*
находится в a
a
в END
блокawk -f test.awk fileA DB
ABCD 2
HIJKL 0
EFG 3
MNO 0
PQRSTU 0