Вы можете упростить эту строку:
number_of_times=`cat $filename | grep $line | wc -l`
до:
number_of_times=$(grep -c "$line" "$filename")
Использование $(...)
вместо обратных кавычек особенно полезно, когда вам необходимо вложить выполнение команды. Вы можете считать вхождения с помощью grep
, и вам никогда не нужно было использовать cat
. Рекомендуется заключать имена файлов в переменные в двойные кавычки на тот случай, если имена файлов заканчиваются пробелами.
Редактирование файла, на котором вы используете cat
, не очень хорошая идея. Из-за того, как вы работаете, начальный cat
будет отображать каждую строку исходного файла по очереди, полностью игнорируя любые изменения, которые вы вносите в (другой) файл с тем же именем с помощью команд редактирования. Вот почему некоторые из ваших имен часто появляются в выводе.
Однако в основном вы пытаетесь подсчитать количество вхождений каждой строки в файле. Обычно это делается с помощью:
sort "$filename" |
uniq -c
sort
группирует все идентичные наборы строк в файле, а uniq -c
подсчитывает количество вхождений каждой отдельной строки. Тем не менее, он выводит счетчик перед строкой, поэтому его нужно обратить вспять & mdash; мы можем использовать sed
для этого. Итак, ваш скрипт может быть просто:
sizefile="/home/b/Desktop/CalcfileSizeGreater40.txt"
rm -f "$sizefile"
filename="/home/b/Desktop/fileSizeGreater40.txt"
sort "$filename" |
uniq -c |
sed 's/^[ ]*\([0-9][0-9]*\)[ ]\(.*\)/\2 : \1/' > "$sizefile"
Я бы с осторожностью использовал rm -fr
на вашем CalcfileSizeGreater40.txt
; rm -f
достаточно для файла, и вы, вероятно, не хотите удалять вещи, если это не файл, а каталог.
Одним приятным побочным эффектом этого является то, что код намного более эффективен, чем оригинал, поскольку он делает один проход через файл (если только он не настолько большой, что сортировка должна разбить его на части для обработки).
Я нахожу код sed
немного сложным для отслеживания.
Я должен был объяснить, что [ ]
биты предназначены для представления пробела и табуляции. На моей машине кажется, что uniq
генерирует только пробелы, так что вы можете упростить это до:
sed 's/^ *\([0-9][0-9]*\) \(.*\)/\2 : \1/'
Регулярное выражение ищет начало строки, любое количество пробелов, а затем число (которое запоминается как \1
из-за \(...\)
, заключающего его), за которым следует пробел и затем «все остальное» , который также запоминается (как '\ 2'). Затем замена печатает «все остальное», за которым следуют пробел, двоеточие, пробел и число.