一个字符串替换小工具 (2013.12.28 updated)

来源:互联网 发布:索尼电视是什么软件 编辑:程序博客网 时间:2024/05/17 22:09

背景: 我用若干个不同的配置文件大同小异,只是几个参数不同。如果一个个手工去修改,非常繁琐。于是有下面的:

/*in-place replace mth line 's nth word with val,  keeping spaces as original as possible.not support tab, you may use:  sed -i 's/\t/    /g' inputfileusage example: find . -name config.mak -exec ./file-inplace {} 260 3 '2#' \;if on linux, keep PC dos ending: find . -name config.mak -exec unix2dos {} \; author: ludi 2013.12*/#include <stdio.h>#include <stdlib.h>#include <string.h>char line[9192];int word_len(char *w){int len = 0;/*while(!isspace(*w)){++w; ++len;} <-- can't handle non-ascii*/for(;*w; ++w){if(' ' == *w || '\n' == *w || '\t' == *w){break;}++len;}return len;}int work(char *line, int n, char *val){char *ptr = line;int wlen, vlen, s = 0, cnt = 0;for(; *ptr; ++ptr){if(*ptr!= ' '){s = 1;}else if(1 == s){++cnt;s = 0;}if(cnt == n){while(*ptr == ' ')++ptr;wlen = word_len(ptr);vlen = strlen(val);if(vlen > wlen){if(ptr[vlen] != ' ')memmove(ptr+vlen+1, ptr+wlen+1, strlen(ptr+wlen+1));strncpy(ptr, val, vlen);ptr[vlen] = ptr[vlen] ? ' ': '\n';}else{strncpy(ptr, val, vlen);ptr += vlen;while(*ptr != ' ' && *ptr != '\n' && *ptr != '\t')*ptr++ = ' ';}break;}}}int main(int ac, char **av){int mth, nth;char *val, *tmpname = "xx.tmp";FILE *fp, *tp;int i, ch;if(ac < 5)return printf("usage: file-in-replace inputfile mth nth val\n");fp = fopen(av[1], "r+");tp = fopen(tmpname, "w+");if(!fp||!tp){return printf("can't open %s", av[1]);}mth = atoi(av[2]);nth = atoi(av[3]);val = av[4];for(i = 1; ; ++i){memset(line, 0, sizeof(line));if(!fgets(line, sizeof(line), fp)){break;}if(i == mth){work(line, nth-1, val);}fprintf(tp, "%s", line);}rewind(fp);rewind(tp);/*while(!feof(tp))fputc(fgetc(tp), fp);*/while((ch = fgetc(tp)) != EOF){fputc(ch, fp);}fclose(fp);fclose(tp);remove(tmpname);return 0;}


 

 最先我也尝试过gawk, sed, 发现gawk 不能保留空格,这影响源文件的对齐。于是抽象了一个line-in-replace, 用这样的方案:

 FILE=def.txt NR=160 COL=2 VAL=259
 TMP=$(head -n $NR  $FILE  | tail -n 1 | ./line-in-replace $COL $VAL)
 LANG=C sed -i -e "$NR s/.*/$TMP/" $FILE

那个LANG是为了处理中文,必须有,不然sed不正常。

后来觉得这三行复制粘贴也太麻烦,于是就整出了上面的file-in-replace。

贴在这里是为了记录我遇到的问题,一遍以后查。

 

 

 

 

0 0
原创粉丝点击