Иначе, если бы вы буквально хотели повторно запустить скрипт:
else
exec $0
Этот процесс отображает количество вхождений слов, включенных в текстовые файлы, расположенные в каталоге или подкаталогах, для каждого файла и во всех файлах.
Результатом является список слов, и каждое слово в списке затем подсчитывается в каждом файле последовательно, а также в объединенных файлах.
find. -type f -exec cat {} \;
find
ищет все текстовые файлы в текущем каталоге или подкаталогах и вызывает cat
для объединения всех соответствующих файлов.
Слова могут быть размещены отдельно в каждой строке для создания списка слов. :каждый символ, кроме буквы, заменяется новой строкой, затем последовательность новых строк заменяется одной новой строкой.
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)
Подстановка команды позволяет сохранить вывод конвейера в переменной.
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
Попробуйте этот код. при необходимости внесите коррективы
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
Использование 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
Попробуйте это,
# 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
Пояснение:
Включено в качестве комментариев внутри скрипта.
Характеристики:
grep
понимает как разделитель слов. Если вы не хотите писать код, а просто используете быстрый способ узнать результаты, вы можете использовать эту команду:
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