📄 text_search.c
字号:
/* text_search.c -- Magic C++ file search and replace (Mostly) portable public-domain implementation -- Copyright(C) 2003 Magicunix Infomation Technology Limited This file is part of magicd. magicd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. For details, see the Magic C++ World-Wide-Web page, `http://www.magicunix.com', or send a mail to the Magic C++ developers <support@magicunix.com>. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <errno.h>#include <stdarg.h>#include <dirent.h>#include <regex.h>#include <ctype.h>#include <fnmatch.h>#include "tools.h"#include "text_search.h"#include "info.h" /*this file is generated by Makefile dynamically,it's include prefix dir*/int nTotalMatch;int nFileMatch;int debug = 0;regex_t g_reg;/*report error*/int report_find_err(int fd ,const char *fmt, ...){ int i; va_list args; char buf[10240]; memset( buf , 0 , sizeof( buf )); va_start(args, fmt); i=vsprintf(buf,fmt,args); va_end(args); write( fd , buf , strlen( buf ));}/*text searchfd -- file descriptor servpf -- name of serverszPath -- pathszTarget -- find targetbRegular -- if it's a regular text searchbSubDir -- if it's recursive searchbCase -- if it's case sensitivity bWholeWord -- if it's whole word matchszReplaceWith -- replace ,if unnecessary , it's value is 0*/int text_search(int fd , char *servpf ,char *szFileTypes, char *szPath , char *szTarget, int bRegular , int bSubDir , int bCase , int bWholeWord , char *szReplaceWith){ char seps[] = ";"; char szFileTypesTmp[200]; DIR *dirp = 0; struct dirent *dp; int i; strcpy( szFileTypesTmp , szFileTypes ); dirp = opendir( szPath ); if( strcmp( szPath , "/dev") == 0 || strcmp( szPath , "/proc") == 0 ) return 0; if( !dirp ) { report_find_err(fd , "open dir:%s failed!:%s\n" ,szPath , strerror(errno)); return -1; } errno = 0; while( ( dp = readdir( dirp ) ) != NULL ) { char szFileName[200]; char *token = NULL; struct stat sbuf; int nLen = strlen( szPath ); memset( szFileName , 0 , sizeof( szFileName )); strcpy( szFileName , szPath ); if( szPath[ nLen - 1 ] != '/' ) strcat( szFileName , "/" ); strcat( szFileName , dp->d_name ); /*check if it's direcotry*/ if( stat( szFileName , &sbuf )== -1 ) { report_find_err(fd , "get attributes of file :%s failed!\n" , szFileName); return -1; } if( S_ISDIR( sbuf.st_mode ) ) { if( !strcmp(dp->d_name , "." ) ||!strcmp(dp->d_name , ".." ) ) continue; /*call recursively*/ else if( bSubDir == 1 ) { text_search(fd ,servpf ,szFileTypes, szFileName ,szTarget, bRegular , bSubDir , bCase , bWholeWord , szReplaceWith); } else continue; } /*match all tokens*/ strcpy( szFileTypesTmp , szFileTypes ); token = strtok( szFileTypesTmp, seps ); while( token != NULL ) { /*it's the same with specified file name */ if( fnmatch( token , dp->d_name , 0 ) == 0 ) { int nret; nret = text_search_in_file(fd , servpf ,szFileName, szTarget, bRegular , bCase , bWholeWord , szReplaceWith); if( nret > 0 ) { nTotalMatch += nret; nFileMatch++; } break; } token = strtok( NULL, seps ); } } closedir( dirp ); return 0;}/*replace and search in a single file*/int text_search_in_file(int fd , char *servpf ,char *szFileName, char *szTarget, int bRegular , int bCase , int bWholeWord , char *szReplaceWith){ FILE *fdSeearch = NULL; FILE *fdTemp = NULL; char szTempFile[300]; int n ; int nLineIndex = 0; char line[10240]; int iMatch = 0; int nstyle; int nFind = 0; if(( fdSeearch = fopen(szFileName,"r")) == NULL) { report_find_err(fd , "get attributes of file :%s failed!:%s\n" , szFileName , strerror(errno)); return -1; } /*generate temp file*/ memset(szTempFile , 0 , sizeof( szTempFile)); if( szReplaceWith != NULL) { sprintf( szTempFile , "%s__removetemp__" , szFileName ); if( !( fdTemp = fopen( szTempFile , "w" ))) { report_find_err(fd , "open temp file failed!:%s\n" , strerror(errno)); return -1; } } nstyle = util_getfilestyle( fdSeearch ); memset( line , 0 , sizeof( line )); nFind = 0; while( ( n = util_getlineex(fdSeearch,1023,line,nstyle) ) != -1 ) { char newline[10240]; char szWrite[10240]; nLineIndex ++; memset( newline , 0 , sizeof( newline )); memset( szWrite , 0 , sizeof( szWrite )); if( search_string( line , szTarget , bRegular , bCase ,bWholeWord ,szReplaceWith , newline) != -1 ) { char szWrite[10240] ; nFind = 1; memset( szWrite , 0 , sizeof( szWrite )); if( szReplaceWith == NULL ) sprintf( szWrite , "//%s%s(%d):%s\r\n", servpf , szFileName ,nLineIndex , newline ); else sprintf( szWrite , "//%s%s(%d):replaced to: %s\r\n", servpf , szFileName ,nLineIndex , newline ); write( fd , szWrite , strlen( szWrite ) ); iMatch ++; } if( szReplaceWith ) { fprintf(fdTemp , "%s\n", newline ); } memset( line , 0 , sizeof( line )); } fclose(fdSeearch); if( szReplaceWith != NULL) { fclose(fdTemp); } if( szReplaceWith ) { /*replace the file with temporary file*/ if( nFind ) { if( rename( szTempFile , szFileName ) == -1 ) { report_find_err(fd , "move temp file %s to file %s failed!:%s\n", szTempFile , szFileName , strerror(errno)); return -1; } } else /*remove temporary file*/ { if( unlink( szTempFile ) == -1 ) { report_find_err(fd , "remove temp file %s failed!:%s\n", szTempFile , strerror(errno)); return -1; } } } return iMatch;}/*search token in a string*/int search_string(char * line ,char * szTarget ,int bRegular ,int bCase , int bWholeWord ,char *szReplaceWith ,char * newline ){ char *curptr; char *ptr ; int nlen; int breplaced = 0; /*at least one replacement happened*/ int z; strcpy( newline , line); curptr = newline; for(;;) { /*regular search*/ if( bRegular ) { regmatch_t pm[1]; const size_t nmatch = 1; char *szTomatch; szTomatch = strdup( curptr ); if( bCase == 0 ) { util_strupr( szTomatch ); } z = regexec(&g_reg , szTomatch , nmatch , pm , 0); if( z == REG_NOMATCH ) { ptr = NULL; nlen = 0; } /*match success*/ else if( !z ) { ptr = curptr + pm[ 0 ].rm_so; nlen = pm[ 0 ].rm_eo - pm[ 0 ].rm_so; } free( szTomatch ); } /*normal search*/ else { char *szTomatch; char *szTargetTmp; char *ptrTmp; szTargetTmp = strdup( szTarget ); if( bCase == 0 ) { util_strupr( szTargetTmp ); } szTomatch = strdup( curptr ); if( bCase == 0 ) { util_strupr( szTomatch ); } ptrTmp = strstr( szTomatch , szTargetTmp ); ptr = ptrTmp ? curptr + (ptrTmp - szTomatch) : NULL; nlen = strlen( szTarget ); free( szTargetTmp ); free( szTomatch ); } if( ptr == NULL ) { if( breplaced == 1 ) return 0; return -1; } if( bWholeWord == 0 ) { if( szReplaceWith != NULL ) { /*continue searching for search type is replacing */ breplaced = 1; /*update scan string*/ replace_string(curptr , ptr - curptr , nlen , szReplaceWith ); curptr = ptr + 1; continue; } /*no need whole word search , return immediately*/ return 0; } if ( ptr > curptr && (isalnum(ptr[-1]) || ptr[-1] == ('_'))) { /*nCur += (pszPos - szToFindTmp);*/ curptr = ptr + 1; continue; } if (isalnum(ptr[nlen]) || ptr[nlen] == ('_')) { /*nCur += (pszPos - pszFindWhere + 1);*/ curptr = ptr + 1; continue; } if( szReplaceWith != NULL ) { breplaced = 1; replace_string(newline , ptr - curptr , nlen , szReplaceWith ); curptr = ptr + 1; continue; } return 0; }}/*replace textreplace string begin with "nBegin" and length is "nLen" with "strReplaceTo"return szNew*/int replace_string( char * szReplace ,int nBegin ,int nLen ,char * szReplaceTo ){ char szNew[10240]; memset( szNew , 0 , sizeof( szNew )); if( nBegin + nLen > strlen( szReplace )) return -1; strncpy( szNew , szReplace , nBegin ); strcat( szNew , szReplaceTo ); strcat ( szNew , szReplace + nBegin + nLen); strcpy( szReplace , szNew ); return 0;}/*main program*//*textsearch -i -e -w -s target path server filetype*//*-i ignore case*//*-e *regular search//*-r xxx replace with*//*-w whole word search*//*-s check sub directories*/int main(int argc , char **argv){ int optch; int bCase = 1; int bRegular = 0; char *szReplaceWith = 0; int bsub = 0; int bWholeWord = 0; static char optstring[] = "ier:ws"; char target[100]; char path[1024]; char serv[100]; char filetype[100]; while( (optch = getopt( argc , argv , optstring ) ) != -1 ) { switch( optch ) { case 'i': bCase = 0; break; case 'e': bRegular = 1; break; case 'r': szReplaceWith = strdup( optarg ); break; case 'w': bWholeWord = 1; break; case 's': bsub = 1; break; } } if( argc - optind < 4 ) { printf("Usage: textsearch -iews[r replacewith] target path server filetype\r\n"); printf("-i :no case match\r\n"); printf("-e :regular match\r\n"); printf("-r replacewith :replace with the text\r\n"); printf("-w :whole word match"); printf("-s :search sub directory\r\n"); if( szReplaceWith ) free( szReplaceWith ); exit(-1); } memset( target , 0 , sizeof( target )); memset( path , 0 , sizeof( path )); memset( serv , 0 , sizeof( serv )); memset( filetype , 0 , sizeof( filetype )); strcpy( target , argv[ optind++ ] ); strcpy( path , argv[ optind++ ] ); strcpy( serv , argv[ optind++ ] ); strcpy( filetype , argv[ optind++ ] ); if( bRegular ) { int z; char *szTargetTmp; szTargetTmp = strdup( target ); if( bCase == 0 ) { util_strupr( szTargetTmp ); } z = regcomp( &g_reg , szTargetTmp , REG_EXTENDED); if( z ) { util_err_log("compile regular express failed!\n",__FILE__,__LINE__, z ); free(szTargetTmp); return -1; } free(szTargetTmp); } nTotalMatch = 0; /*count of matched lines*/ nFileMatch = 0; /*count of matched files*/ text_search( 1 , serv,filetype, path , target , bRegular ,bsub , bCase , bWholeWord , szReplaceWith ); if( szReplaceWith == NULL ) printf("Find %d occurence(s) in %d file(s)!\r\n", nTotalMatch , nFileMatch ); else printf("Replace %d occurence(s) in %d file(s)!\r\n", nTotalMatch , nFileMatch ); if( szReplaceWith ) free( szReplaceWith ); if( bRegular ) regfree(&g_reg); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -