Автоматизировать подсчет количества вхождений

Если вы измените уровень масштабирования и настроите на вид значка в определенной папке, он «запомнит» это до большого, но конечного количества папок.

3
задан 19 June 2017 в 17:17

11 ответов

Мое предложение:

IFS=; while read -r word; do printf "%s " $word; grep -o $word b | wc -l; done < a
, используя while, мы зацикливаемся на слова (файл a) printf "%s " $word: печатает имя слова, например: ABCD grep -o $word b | wc -l: подсчитывает и печатает номер вхождения
6
ответ дан 22 May 2018 в 21:23
  • 1
    Это намного лучше, чем моя версия bash, и более портативная. – Sergiy Kolodyazhnyy 19 June 2017 в 08:04

Мое предложение:

IFS=; while read -r word; do printf "%s " $word; grep -o $word b | wc -l; done < a , используя while, мы зацикливаемся на слова (файл a) printf "%s " $word: печатает имя слова, например: ABCD grep -o $word b | wc -l: подсчитывает и печатает номер вхождения
6
ответ дан 18 July 2018 в 11:26

Мое предложение:

IFS=; while read -r word; do printf "%s " $word; grep -o $word b | wc -l; done < a , используя while, мы зацикливаемся на слова (файл a) printf "%s " $word: печатает имя слова, например: ABCD grep -o $word b | wc -l: подсчитывает и печатает номер вхождения
6
ответ дан 24 July 2018 в 19:47

Сценарий Python

count_patterns.py. Должно быть достаточно хорошо для больших файлов. Использует OrderedDict для записи всех паттернов из файла A, предоставленных в командной строке, и ищет их в файле B.

#!/usr/bin/env python3
import sys
from collections import OrderedDict as od

pattern=od()
with open(sys.argv[1]) as pattern_file, open(sys.argv[2]) as data_file:

    for line in pattern_file:
        pattern[line.strip()]=0

    for line in data_file:
        for p in pattern.keys():
            pattern[p]+=line.strip().count(p)

for key,val in pattern.items():
    print(key,val)

Использование:

$ ./count_patterns.py file_A.txt file_B.txt 
ABCD 4
EFG 3
HIJKL 0
MNO 1
PQRSTU 0

Bash.

Здесь используется подстановка процесса из sed, которая позволяет разделить файл A на строки новой строки в ** и использовать grep -c для подсчета числа совпадающих строк.

[ f3]

Не лучший способ сделать это, возможно, не подходит для больших файлов, но работает. Не рекомендуется использовать метод bash, но если набор данных невелик, он будет работать.

6
ответ дан 22 May 2018 в 21:23

Bash

Использование ассоциативных массивов 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

Python 3

Использование пользовательского словарный класс и обработка функциональных стилей:

#!/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

C ++

#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
5
ответ дан 22 May 2018 в 21:23

Вот программа 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]
    }
}

Как?

Установить поле seperaotr to * 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
4
ответ дан 22 May 2018 в 21:23

Bash

Использование ассоциативных массивов 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

Python 3

Использование пользовательского словарный класс и обработка функциональных стилей:

#!/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

C ++

#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
5
ответ дан 18 July 2018 в 11:26

Сценарий Python

count_patterns.py. Должно быть достаточно хорошо для больших файлов. Использует OrderedDict для записи всех паттернов из файла A, предоставленных в командной строке, и ищет их в файле B.

#!/usr/bin/env python3 import sys from collections import OrderedDict as od pattern=od() with open(sys.argv[1]) as pattern_file, open(sys.argv[2]) as data_file: for line in pattern_file: pattern[line.strip()]=0 for line in data_file: for p in pattern.keys(): pattern[p]+=line.strip().count(p) for key,val in pattern.items(): print(key,val)

Использование:

$ ./count_patterns.py file_A.txt file_B.txt ABCD 4 EFG 3 HIJKL 0 MNO 1 PQRSTU 0

Bash.

Здесь используется подстановка процесса из 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, но если набор данных невелик, он будет работать.

6
ответ дан 18 July 2018 в 11:26

Вот программа 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] } }

Как?

Установить поле seperaotr to * 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
4
ответ дан 18 July 2018 в 11:26

Bash

Использование ассоциативных массивов 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

Python 3

Использование пользовательского словарный класс и обработка функциональных стилей:

#!/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

C ++

#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
5
ответ дан 24 July 2018 в 19:47

Вот программа 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] } }

Как?

Установить поле seperaotr to * 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
4
ответ дан 24 July 2018 в 19:47

Другие вопросы по тегам:

Похожие вопросы: