1 метод будет
sudo find / -type f | wc -l
sudo find / -type d | wc -l
(sudo для предотвращения доступа к ошибкам)
f для файлов, d для каталогов.
The / proc / файловая система будет выходить из строя, но я не рассматриваю эти файлы;)
Вы можете сделать это с помощью небольшого скрипта Python:
#!/usr/bin/env python3
import sys
if len(sys.argv) != 2:
print("You must provide exactly one filename to read as argument.")
exit(-1)
file = open(sys.argv[1])
file.readline() # to strip headline
dict = {}
for line in file:
datestr, tempstr = line.split()[4:]
year, temp = int(datestr.split("/")[-1]), float(tempstr)
dict.setdefault(year, []).append(temp)
for year in dict:
print("{0}:\t{1:.2f}".format(year, sum(dict[year]) / len(dict[year])))
Он читает файл, указанный как аргумент, при выполнении сценария по строкам и создает словарь, который отображает годы в списки значений температуры. После обработки всего файла он будет вычислять и печатать средние температуры в год.
Ниже приведен пример с файлом данных vk4.txt, который вы указали. Я сохранил сценарий выше как avgtemp.py в текущем каталоге и сделал его исполняемым с помощью chmod +x avgtemp.py:
$ ./avgtemp.py vk4.txt
2012: 32.22
2013: 34.30
. Если вы хотите, точный формат вывода можно легко изменить, просто отредактировав "{0}:\t{1:.2f}" в последней строке скрипта. Здесь вы можете ввести любой шаблон, если он содержит {0}, чтобы заменить его на год и {1:.2f} или аналогичный, чтобы заменить его на среднюю температуру, отображаемую двумя десятичными цифрами. [F9] - вкладка.
Это может быть больше подходит для переполнения стека; однако, вот решение, использующее Python, в котором вы должны заменить temperature_data.txt в первой строке вашим файлом.
f=open("temperature_data.txt","r") ### REPLACE temperature_data.txt WITH THE FILE CONTAINING YOUR DATA
flines=f.readlines() #read the file in question
f.close()
flines_split=[line.split() for line in flines] #split each line up
data_split=[line for line in flines_split if len(line)>=5 and line[4].count("/")==2] #get only lines with the date in
gathered_data={}
for line in data_split: #this block sanitises the data
month=int(line[4][:2]) ### NOTE THAT THIS ASSUMES YOU ARE USING AMERICAN DATE FORMAT
### IF YOU ARE NOT, REPLACE "month=int(line[4][:2])" WITH "month=int(line[4][3:5])"
year=int(line[4][6:])
if (month,year) in gathered_data:
gathered_data[(month,year)].append(float(line[5]))
else:
gathered_data[(month,year)]=[float(line[5])]
def mean(l): #function to calculate means
return sum(l)/float(len(l))
means={k:mean(gathered_data[k]) for k in gathered_data} #calculate means
print("Month Year Temperature")
for k in sorted(list(means)): #print output
print("{date[0]:^5} {date[1]} {temp:.4}".format(date=k,temp=means[k])) ### the 4 in {temp:.4} specifies precision and can be modified.
Вот однострочная команда, которая работает с предпосылкой построения двух хэшей - $h1 для суммирования значений температуры и $h2 для хранения общего количества обработанных записей. Каждая соответствующая строка будет содержать тот же ключ в формате MMYYYY, который извлекается из вашего столбца №5 (который для индекса perl массива # 4, то есть $F[4]):
perl -lane 'do{ @a=split "/",$F[4]; $k= $a[0] . $a[2]; $h1{$k}+=$F[5] and $h2{$k}+=1 } if $. != 1 and $F[4]; END{ do {print $_," ",$h1{$_}/$h2{$_} } for keys %h1; }'
Ключевые точки здесь:
используем do {} if condition1 and condition2 структура. Действие {} выполняется только тогда, когда номер строки не равен 1 (т. Е. Мы пропускаем заголовок), и существует $F[4] (т. Е. Мы избегаем пустых или неполных строк). @a=split "/",$F[4] позволяет нам разбивать штамп даты MM/DD/YYYY на части, а с помощью $k= $a[0] . $a[2] мы создаем ключевую переменную, которая позволит нам хранить данные в двух хэшах. Структура END{} будет выполнять действие, когда весь файл будет считан.Решение работает достаточно хорошо. Вот тест с 1100 000 строк ввода:
bash-4.3$ time perl -lane 'do{ @a=split "/",$F[4]; $k= $a[0] . $a[2]; $h1{$k}+=$F[5] and $h2{$k}+=1 } if $. != 1 and $F[4]; END{ do {print $_," ",$h1{$_}/$h2{$_} } for keys %h1; }' big_input.txt
052012 32.4666666666021
042012 31.8250000001141
042013 34.3000000000646
real 0m8.600s
user 0m8.480s
sys 0m0.032s
bash-4.3$ wc -l big_input.txt
1100000 big_input.txt
ПРИМЕЧАНИЕ: для формата csv используйте perl -a -F',' -lne вместо
Основная идея будет заключаться в создании ключа года из поля даты, а затем суммирования и подсчета записей на основе этого ключа с использованием ассоциативных массивов, например
awk '
NR>1 {
split($5,d,"/"); s[d[3]"/"d[1]]+=$6; c[d[3]"/"d[1]]++;
}
END {
for (i in s) print i, s[i]/c[i]
}' vk4.txt
Тестирование с вашими данными:
$ mawk '
NR>1 {
split($5,d,"/"); s[d[3]"/"d[1]]+=$6; c[d[3]"/"d[1]]++;
}
END {
for (i in s) print i, s[i]/c[i];
}' vk4.txt
2012/04 31.9667
2012/05 32.4667
2013/04 34.3
Если у вас есть GNU awk (gawk) v4 +, вы можете добавить явную сортировку.
Вы можете сделать это с помощью небольшого скрипта Python:
#!/usr/bin/env python3
import sys
if len(sys.argv) != 2:
print("You must provide exactly one filename to read as argument.")
exit(-1)
file = open(sys.argv[1])
file.readline() # to strip headline
dict = {}
for line in file:
datestr, tempstr = line.split()[4:]
year, temp = int(datestr.split("/")[-1]), float(tempstr)
dict.setdefault(year, []).append(temp)
for year in dict:
print("{0}:\t{1:.2f}".format(year, sum(dict[year]) / len(dict[year])))
Он читает файл, указанный как аргумент, при выполнении сценария по строкам и создает словарь, который отображает годы в списки значений температуры. После обработки всего файла он будет вычислять и печатать средние температуры в год.
Ниже приведен пример с файлом данных vk4.txt, который вы указали. Я сохранил сценарий выше как avgtemp.py в текущем каталоге и сделал его исполняемым с помощью chmod +x avgtemp.py:
$ ./avgtemp.py vk4.txt
2012: 32.22
2013: 34.30
. Если вы хотите, точный формат вывода можно легко изменить, просто отредактировав "{0}:\t{1:.2f}" в последней строке скрипта. Здесь вы можете ввести любой шаблон, если он содержит {0}, чтобы заменить его на год и {1:.2f} или аналогичный, чтобы заменить его на среднюю температуру, отображаемую двумя десятичными цифрами. [F9] - вкладка.
Это может быть больше подходит для переполнения стека; однако, вот решение, использующее Python, в котором вы должны заменить temperature_data.txt в первой строке вашим файлом.
f=open("temperature_data.txt","r") ### REPLACE temperature_data.txt WITH THE FILE CONTAINING YOUR DATA
flines=f.readlines() #read the file in question
f.close()
flines_split=[line.split() for line in flines] #split each line up
data_split=[line for line in flines_split if len(line)>=5 and line[4].count("/")==2] #get only lines with the date in
gathered_data={}
for line in data_split: #this block sanitises the data
month=int(line[4][:2]) ### NOTE THAT THIS ASSUMES YOU ARE USING AMERICAN DATE FORMAT
### IF YOU ARE NOT, REPLACE "month=int(line[4][:2])" WITH "month=int(line[4][3:5])"
year=int(line[4][6:])
if (month,year) in gathered_data:
gathered_data[(month,year)].append(float(line[5]))
else:
gathered_data[(month,year)]=[float(line[5])]
def mean(l): #function to calculate means
return sum(l)/float(len(l))
means={k:mean(gathered_data[k]) for k in gathered_data} #calculate means
print("Month Year Temperature")
for k in sorted(list(means)): #print output
print("{date[0]:^5} {date[1]} {temp:.4}".format(date=k,temp=means[k])) ### the 4 in {temp:.4} specifies precision and can be modified.
Вот однострочная команда, которая работает с предпосылкой построения двух хэшей - $h1 для суммирования значений температуры и $h2 для хранения общего количества обработанных записей. Каждая соответствующая строка будет содержать тот же ключ в формате MMYYYY, который извлекается из вашего столбца №5 (который для индекса perl массива # 4, то есть $F[4]):
perl -lane 'do{ @a=split "/",$F[4]; $k= $a[0] . $a[2]; $h1{$k}+=$F[5] and $h2{$k}+=1 } if $. != 1 and $F[4]; END{ do {print $_," ",$h1{$_}/$h2{$_} } for keys %h1; }'
Ключевые точки здесь:
используем do {} if condition1 and condition2 структура. Действие {} выполняется только тогда, когда номер строки не равен 1 (т. Е. Мы пропускаем заголовок), и существует $F[4] (т. Е. Мы избегаем пустых или неполных строк). @a=split "/",$F[4] позволяет нам разбивать штамп даты MM/DD/YYYY на части, а с помощью $k= $a[0] . $a[2] мы создаем ключевую переменную, которая позволит нам хранить данные в двух хэшах. Структура END{} будет выполнять действие, когда весь файл будет считан.Решение работает достаточно хорошо. Вот тест с 1100 000 строк ввода:
bash-4.3$ time perl -lane 'do{ @a=split "/",$F[4]; $k= $a[0] . $a[2]; $h1{$k}+=$F[5] and $h2{$k}+=1 } if $. != 1 and $F[4]; END{ do {print $_," ",$h1{$_}/$h2{$_} } for keys %h1; }' big_input.txt
052012 32.4666666666021
042012 31.8250000001141
042013 34.3000000000646
real 0m8.600s
user 0m8.480s
sys 0m0.032s
bash-4.3$ wc -l big_input.txt
1100000 big_input.txt
ПРИМЕЧАНИЕ: для формата csv используйте perl -a -F',' -lne вместо
Основная идея будет заключаться в создании ключа года из поля даты, а затем суммирования и подсчета записей на основе этого ключа с использованием ассоциативных массивов, например
awk '
NR>1 {
split($5,d,"/"); s[d[3]"/"d[1]]+=$6; c[d[3]"/"d[1]]++;
}
END {
for (i in s) print i, s[i]/c[i]
}' vk4.txt
Тестирование с вашими данными:
$ mawk '
NR>1 {
split($5,d,"/"); s[d[3]"/"d[1]]+=$6; c[d[3]"/"d[1]]++;
}
END {
for (i in s) print i, s[i]/c[i];
}' vk4.txt
2012/04 31.9667
2012/05 32.4667
2013/04 34.3
Если у вас есть GNU awk (gawk) v4 +, вы можете добавить явную сортировку.