LINUX.ORG.RU

маленькая програмка чтобы вытащить числа из лога


0

0

пару недель назад столкнулся с такой проблемой. был лог, и из этого лога нужно было вытащить числа, сложить и посчитать среднее арифметическое. я не нашёл никакой тулзы или редактора который бы мог сделать это автоматом и не нужно было клацать на калькуляторе 150 чисел вручную (хотя не исключено что вим это умеет). вот кусок лога: [demod/stv362/s362lock.c:189][0] s362_Lock() Status[2] Time[500ms] [demod/stv362/s362lock.c:189][0] s362_Lock() Status[2] Time[400ms] [demod/stv362/s362lock.c:189][0] s362_Lock() Status[2] Time[1800ms] [demod/stv362/s362lock.c:189][0] s362_Lock() Status[2] Time[500ms] мне нужно было вытащить эти самые миллисекунды. я решил не заморачиваться поисками и написал такую простенькую программку, которая это делает. в данный момент нет поддержки связанных списков для файлов неопределённого размера, не поддерживается обработка того, что время попадается 2 раза в строке, и нет защиты от переполнения unsigned int переменной. В общем-то хотелось бы послушать какие ещё тут могут быть бока, а также про неоптимальность алгоритма и т.д. и т.п. ;)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


char *version="0.53";
#define CHARS_PER_STRING 300
//#define DEBUG_ENABLE


FILE * file_ptr;
int times[300];  // strings in file

int FileScan(FILE* file_ptr, const char * sequence)
{
	unsigned int i;
	unsigned int sequence_size=0;
	unsigned int total=0;
	unsigned char have_sequence=0;
	char tmp_string[CHARS_PER_STRING];   //array to contain one string
	char * tmp_str_ptr;
  char digit[10];
  int digit_cnt=0;
	unsigned int strings_seq_cnt=0;     //strings with sequence found
	unsigned int strings_total_cnt=0;   //total number of strings in file

	sequence_size=strlen(sequence);
  
#ifdef DEBUG_ENABLE
	printf ("sequence: %s \n", sequence);
	printf("size of seq %d\n", sequence_size);
#endif

	//working till the EOF, one iteration == one string have read
	while ( fgets(tmp_string,CHARS_PER_STRING,file_ptr) != NULL )
	{
		tmp_str_ptr=tmp_string;
		have_sequence=0;
  		while (*tmp_str_ptr)
  		{
    			if (*tmp_str_ptr == *sequence)
    			{
      				if ( !strncmp(tmp_str_ptr,sequence,sequence_size) ) //if we found Time[
      				{
#ifdef DEBUG_ENABLE
					printf("seq found\n");
#endif
		        		tmp_str_ptr += sequence_size ;   //set pointer to time digits
        				while (*tmp_str_ptr >= '0' && *tmp_str_ptr <= '9')
        				{
	  					if (digit_cnt >= 10)
	  					{
	  						printf("[error] value found is too big. \n");
							return 1;
	  					}
          					digit[digit_cnt]=*tmp_str_ptr;
          					tmp_str_ptr++;
          					digit_cnt++;
	  					have_sequence=1;
        				}
#ifdef DEBUG_ENABLE
					printf ("digit %d \n",digit_cnt);
#endif
      				}
    			}
    			tmp_str_ptr++;
  		}

		if (have_sequence)
		{
			times[strings_seq_cnt]=atoi(digit);
			strings_seq_cnt++;
		}
  		for (i=0; i<10; i++)
    			digit[i]='a';
  		strings_total_cnt++;  //increased for every cycle iteration, contains number of strings in file
  		digit_cnt=0;

	}

	for (i=0; i<strings_seq_cnt; i++)
 	{
   		total+=times[i];
   		printf ("string: %d time : %d \n",i+1,times[i]);
 	}
 	printf ("strings total:         %d \n",strings_total_cnt);
	printf ("strings with sequence: %d \n",strings_seq_cnt);
	printf ("time sum:              %d \n",total);
 	if (strings_seq_cnt)
		total/=strings_seq_cnt;
	printf ("time~: %d\n",total);

	return 0;
}


int main (int argc , char* argv[])
{
	unsigned int i;

#ifdef DEBUG_ENABLE
	printf("timefromlog started. version: %s\n",version);
	printf("argc=%d\n",argc);
	for (i=0; i<argc; i++)
	{
		printf("argv[%d]: %s\n",i,argv[i]);
	}

#endif
	//parsing input without getopt() ! 
	if (argc == 2)
	{
		if ( !(strcmp(argv[1],"--help") ) )  
			printf ("this is a help for timefromlog program.\nfirst param: filename to search in.\nsecond param: sequence digits start after.\n --help    - this help\n --version - program version\n");
		else if ( !(strcmp(argv[1],"--version") ) )  
			printf ("version: %s  \n", version);
		else
			printf("incorrect params. run program with --help\n");
		return 1;
	}       
	else if (argc != 3)
	{
		printf("incorrect params. run program with --help\n");
		return 1;
	}

	file_ptr=fopen(argv[1],"r");
	if (!file_ptr)
	{
		printf("[error] : can't open file\n");
		return 1;
	}
	else 
		printf("[working] : file opened\n");

	FileScan(file_ptr, argv[2]);
	
	if ( !fclose(file_ptr) )
		printf("[working] : file closed successfully\n");
	else 
		printf("[error] : file can not be closed\n");
  

  return 0;
}

Ответ на: комментарий от www_linux_org_ru

> у меня не пошел -- опции Е нет и say ругается, так что вот:

> perl -e'map{$b+=s/\d+ms/$a+=$&/ge}<>;print$a/$b' logfile

а если только s/-E/-e/ и s/say/print/? на символ короче получается ;) хотя да, с мапом прикольнее смотрится, без пробелов :)

arsi ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.