найдите количество записей в файле и удалите их, используя скрипт оболочки - PullRequest
0 голосов
/ 14 марта 2012

У меня есть следующий код, где я собрал все размеры файлов, превышающие 40 КБ, из моей системы. Я сохранил всю эту информацию в текстовом файле. Мне нужно обработать файл, чтобы прочитать количество раз, когда каждая запись найдена в текстовом файле, и удалить все эти записи. У меня есть следующий код, но он не работает должным образом.

 #! /bin/sh
  rm -rf /home/b/Desktop/CalcfileSizeGreater40.txt
  filename="/home/b/Desktop/fileSizeGreater40.txt"   
  cat $filename | while read line
    do
  number_of_times=`cat $filename | grep $line | wc -l`
  echo $line:$number_of_times
  echo $line : $number_of_times >> /home/b/Desktop/CalcfileSizeGreater40.txt
  sed '/$line/d' $filename  >tmp
  mv tmp $filename
  done

Когда я смотрю на CalcfileSizeGreater40.txt, я вижу

 131072 : 4
 65553 : 9
 65553 : 9
 65553 : 9
 65553 : 9
 65553 : 9
 65553 : 9
131072 : 4
 65553 : 9
 65553 : 9
 65553 : 9

есть идеи, где я иду не так?

Ответы [ 2 ]

3 голосов
/ 14 марта 2012

Вы можете упростить эту строку:

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'). Затем замена печатает «все остальное», за которым следуют пробел, двоеточие, пробел и число.

1 голос
/ 14 марта 2012
sort -g $filename | uniq -c

вы получите (количество раз) в каждой строке

10    500000
1     10000

вам просто нужно поменять местами каждую строку

sort -g $filename | uniq -c | while read a b; do echo $b $a ; done
...