Как сравнить одно и то же слово между несколькими файлами?

Иначе, если бы вы буквально хотели повторно запустить скрипт:

else
 exec $0
4
15.09.2018, 10:54
5 ответов

Этот процесс отображает количество вхождений слов, включенных в текстовые файлы, расположенные в каталоге или подкаталогах, для каждого файла и во всех файлах.

  1. Объединить все текстовые файлы.
  2. Подавление повторяющихся слов.

Результатом является список слов, и каждое слово в списке затем подсчитывается в каждом файле последовательно, а также в объединенных файлах.

  1. Поиск количества вхождений каждого слова в списке.

1. Объединить все текстовые файлы

find. -type f -exec cat {} \;

findищет все текстовые файлы в текущем каталоге или подкаталогах и вызывает catдля объединения всех соответствующих файлов.

2. Подавление повторяющихся слов

Слова могут быть размещены отдельно в каждой строке для создания списка слов. :каждый символ, кроме буквы, заменяется новой строкой, затем последовательность новых строк заменяется одной новой строкой.

tr -cs '[:alpha:]' '[\n*]'

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

sort | uniq

или

sort -u

Примечание:нечувствительный к случаю -поиск может быть выполнен с добавлением следующей команды в конвейер.

tr '[:upper:]' '[:lower:]'

Возможные проблемы

Существующий файл сценария не следует объединять с другими файлами, даже если он расположен в текущем каталоге или в подкаталогах (c.f.man find).

find. -type f \( \! -name "*${0##*/}" \) -exec cat {} \;

Примечание:$0расширяется до имени оболочки. ${PARAMETER##WORD}заменяется на параметр с удаленным самым длинным совпадающим шаблоном (c.f. расширения параметров оболочки ).

Например, /usr/local/bin/myscriptстановится myscript.

Результат

list=$(find. -type f \( \! -name "*${0##*/}" \) -exec cat {} \; | 
           tr -cs '[:alpha:]' '[\n*]' | tr '[:upper:]' '[:lower:]' | sort -u)

Подстановка команды позволяет сохранить вывод конвейера в переменной.

3. Поиск по количеству вхождений...

a )Поиск во всех строках, содержащих заданное слово, каждое вхождение в отдельной строке...

grep --exclude="*${0##*/}" -Rowi $word.

... и подсчитывает количество строк

grep --exclude="*${0##*/}" -Rowi $word. | wc -l

b )Подсчитывает совпадающие строки для каждого входного файла.

grep --exclude="*${0##*/}" -Rowi $word. | tr '[:upper:]' '[:lower:]' |
    uniq -c | sed -E "$sed_script"

Ищет все строки, содержащие заданное слово (каждое вхождение находится в другой строке ), печатает количество вхождений, а также исходный файл и переформатирует данные.

Примечание:$0расширяется до имени оболочки. ${PARAMETER##WORD}заменяется на параметр с удаленным самым длинным совпадающим шаблоном (c.f. расширения параметров оболочки ).

Например, /usr/local/bin/myscriptстановится myscript.

Примечание:--exclude— это расширение GNU, не , указанное для POSIX grep . Если это проблема, удалите этот параметр и добавьте следующий оператор в начало сценария оболочки.

# assign first positional parameter to "dirname"
# and move to this directory

dirname=${1:?first positional parameter missing\!}
cd "$dirname"

Сценарий оболочки

#!/bin/sh

list=$(find. -type f \( \! -name "*${0##*/}" \) -exec cat {} \; | 
           tr -cs '[:alpha:]' '[\n*]' | tr '[:upper:]' '[:lower:]' | sort -u)

# extract data and print formatted data
sed_script='s/([[:digit:]]+) (.*):[[:alpha:]]+/\2:\1/;s/[[:blank:]]+//'

for word in $list; do
    echo $word:$(grep --exclude="*${0##*/}" -Rowi $word. | wc -l)
    grep --exclude="*${0##*/}" -Rowi $word. | tr '[:upper:]' '[:lower:]' | 
        uniq -c | sed -E "$sed_script"
    echo
done | sed -e "/^[[:alpha:]]\+:1/{N;N;d;}"

Ввод

prompt% cat file1
Lorem ipsum dolor sit amet. cat cat
prompt% cat file2
Lorem ipsum dolor sit amet, consectetur adipiscing elit. cat ut
prompt% cat file3
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed tristique egestas massa sed facilisis. Duis hendrerit ut. cat
tristique tristique tristique tristique

Выход

adipiscing:2
./file2:1
./file3:1

amet:3
./file1:1
./file2:1
./file3:1

cat:4
./file1:2
./file2:1
./file3:1

consectetur:2
./file2:1
./file3:1

dolor:3
./file1:1
./file2:1
./file3:1

elit:2
./file2:1
./file3:1

ipsum:3
./file1:1
./file2:1
./file3:1

lorem:3
./file1:1
./file2:1
./file3:1

sed:2
./file3:2

sit:3
./file1:1
./file2:1
./file3:1

tristique:5
./file3:5

ut:2
./file2:1
./file3:1
0
27.01.2020, 20:59

Попробуйте этот код. при необходимости внесите коррективы

bash-4.1$ cat test.sh
#!/bin/bash

OUTPUT_FILE=/tmp/output.txt

awk '{
for(i=1;i<=NF;i++)
{
        Arr[$i]++
}
}
END{
for (i in Arr){
        if(Arr[i]>1)
        {
                print i":"Arr[i]
        }
}
}' file* > ${OUTPUT_FILE}

cat ${OUTPUT_FILE}
echo ""

IFS=":"
while read WORD TOTAL_COUNT
do
        echo "${WORD}:"
        for FILE_NAME in file*
        do
                COUNT=$(tr ' ' '\n' < ${FILE_NAME} | grep -c "${WORD}")
                if [ "${COUNT}" -gt "0" ]
                then
                        echo "${FILE_NAME}:${COUNT}"
                fi
        done
done < ${OUTPUT_FILE}


bash-4.1$ bash test.sh
beautiful:3
so:3

beautiful:
file1:1
file2:1
file3:1
so:
file1:1
file2:1
file3:1
0
27.01.2020, 20:59

Использование grepдля подачи слов и имен файлов, а затем awkдля переформатирования вывода для получения желаемого результата:

grep -Ho '\w\+' file* |
awk -F':' '{ words[$1 FS $2]++; seen[$2]++ }
END{ for (x in seen) {
         print x":" seen[x];
         for (y in words) {
            if (y ~ "\\<" x "\\>")print substr(y, 1, length(y)-length(x)), words[y]
         }
     }
}'

Это даст вам хороший вывод, как показано ниже (оба желаемых вывода за один раз):

so:3
file1: 1
file2: 1
file3: 1
This:1
file1: 1
beautiful:3
file3: 1
file1: 1
file2: 1
There:1
file2: 1
are:1
file2: 1
is:1
file1: 1
0
27.01.2020, 20:59

Попробуйте это,

# Declare the files you want to include
files=( file* )

# Function to find common words in any number of files
wcomm() {
    # If no files provided, exit the function.
    [ $# -lt 1 ] && return 1
    # Extract words from first file
    local common_words=$(grep -o "\w*" "$1" | sort -u)
    while [ $# -gt 1 ]; do
        # shift $1 to next file
        shift
        # Extract words from next file
        local next_words=$(grep -o "\w*" "$1" | sort -u)
        # Get only words in common from $common_words and $next_words
        common_words=$(comm -12 <(echo "${common_words,,}") <(echo "${next_words,,}"))
    done
    # Output the words common to all input files
    echo "$common_words"
}

# Output number of matches for each of the common words in total and per file
for w in $(wcomm "${files[@]}"); do
    echo $w:$(grep -oiw "$w" "${files[@]}" | wc -l);
    for f in "${files[@]}"; do
        echo $f:$(grep -oiw "$w" "$f" | wc -l);
    done;
    echo;
done

Выход:

beautiful:3
file1:1
file2:1
file3:1

so:3
file1:1
file2:1
file3:1

Пояснение:

Включено в качестве комментариев внутри скрипта.

Характеристики:

  • Столько файлов, сколько позволяет ARG _MAX
  • Находит все слова, разделенные чем-либо, что grepпонимает как разделитель слов.
  • Регистр не принимается, поэтому "прекрасный" и "прекрасный" - это одно и то же слово.
1
27.01.2020, 20:59

Если вы не хотите писать код, а просто используете быстрый способ узнать результаты, вы можете использовать эту команду:

cat list_of_words | while read line; do echo $line; grep -riE '$line'-c where_to_look_or_folder; done

-r :read into files
-i: no casesensitive
-E: regexp is useable if you want something more complicated to search
-c: counter

Выход:

word1
path:filename:count

Пример:

cat text | while read line; do echo $line; grep -riE '$line'-c somwhwere/nowhere; done
0
27.01.2020, 20:59

Теги

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