Linux sort命令

1. 用man sort 查看sort的帮助文档

2. sort常用选项功能与使用截图

  • sort的-u选项

它的作用很简单,就是在输出行中去除重复行。

u.txt:

banana
apple
pear
orange
pear

  • sort的-r选项

sort默认的排序方式是升序,如果想改成降序,就加个-r就搞定了。

  • sort的-o选项

由于sort默认是把结果输出到标准输出,所以需要用重定向才能将结果写入文件,形如sort filename > newfile。

但是,如果你想把排序结果输出到原文件中,用重定向不会更新文件,反而会把原文件清空。

  • sort的-n选项

你有没有遇到过10比2小的情况。我反正遇到过。出现这种情况是由于排序程序将这些数字按字符来排序了,排序程序会先比较1和2,显然1小,所以就将10放在2前面喽。这也是sort的一贯作风。
这种状况,就要使用-n选项,来告诉sort,“要以数值来排序”!

  • sort的-t选项和-k选项

如果有一个文件的内容是这样:

banana:30:5.5
apple:10:2.5
pear:90:2.3
orange:20:3.4
peach:40:1.8

这个文件有三列,列与列之间用冒号隔开了,第一列表示水果类型,第二列表示水果数量,第三列表示水果价格。

那么我想以水果数量来排序,也就是以第二列来排序,如何利用sort实现?

幸好,sort提供了-t选项,后面可以设定间隔符。

指定了间隔符之后,就可以用-k来指定列数了。

  • 更复杂一点

data.txt

公司 人数 工资
google 110 5000
baidu 100 5000
guge 50 3000
sohu 100 4500

  • 让fdata.txt按照人数排序 ,人数相同的按照员工平均工资升序排序:

sort -n -t‘ ’ -k 2 -k 3 data.txt

  • 让data.txt按照员工工资降序排序,如果工资相同的,则按照公司人数升序排序

sort -n -t ‘ ‘ -k 3r -k 2 data.txt

  • 其他的sort常用选项

-f会将小写字母都转换为大写字母来进行比较,亦即忽略大小写

-M会以月份来排序,比如JAN小于FEB等等

-b会忽略每一行前面的所有空白部分,从第一个可见字符开始比较。

3. sort实现

写出伪代码和相关的函数或系统调用

本来只想写个最简单的功能,没有参数的,但写着写着,觉得实现个 -o 也不难,
又写着写着,觉得实现个 -r也不难,又写着写着,觉得实现个 -k也不难
再写着写着,觉得实现个 -t加-k 虽然有点难度,但也不是不能实现,
既然都这样了,也没差几个参数了,再实现个 -n、-u 和 -f吧。。。
最后也不差个 -b了

代码全部原创,肯定还是有疏忽之处,欢迎留言评论

Linux C编程

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 100
#include <ctype.h>

//位图(字符图) 
unsigned char flag[10];
char *token;
int key=1;
//-f 小写转大写 
char *strupr(char *str){
    char *orign=str;
    for (; *str!='\0'; str++)
        *str = toupper(*str);
    return orign;
}
//-b 删除前导空格 
char *trim(char *str){
	char *p = str;
	while (*p == ' '){
		p++;
	}
	return p;
}

	/*
		flag[0] : -u
		flag[1] : -r
		flag[2] : -n 
		flag[3] :-o
		flag[4] :-k
		flag[5] : -t
		flag[6] : -b
		flag[7] : -f
	*/
int cmp_string(const void* _a , const void* _b)	//参数格式固定
{
	int result = 0;	
	char *a = (char*)malloc(sizeof((char*)_a));
	strcpy(a,(char*)_a);
    char *b = (char*)malloc(sizeof((char*)_b));
	strcpy(b,(char*)_b);
	
	//-f
	if(flag[7]){
		strupr(a);
		strupr(b); 
	} 
	//-b 删除前导空格 
	if(flag[6]){
		a = trim(a);
		b = trim(b); 
	}
	//不切分 
   	result = strcmp(a,b); 
   	
   	//-k
   	if(flag[4]==1 && flag[5]==0){
   		result = b[key-1] - a[key-1];
	}
	
	//如果-t切分,会分成count个组 
	int count = 1;
	if(flag[5]==1){
		for(int i=0;i<strlen(a);i++){
			if(a[i]==token[0]){
				count++;
			}
		}
	}
	
	char *array1[count];
	char *array2[count];
	
	//-t
	if(flag[5]){
		//split,把字符串a,b分成字符串数组array[1],array[2]
		char * str1;
    	str1 = strtok(a,token);
    	int aut=6;
   	 	int i = 0;
		while( str1 != NULL ) {
			array1[i] = str1;
	     	str1 = strtok(NULL, token);
	      	i++;
	  	}
		char * str2;
    	str2 = strtok(b,token);
   	 	i = 0;
		while( str2 != NULL ) {
			array2[i] = str2;
	     	str2 = strtok(NULL, token);
	      	i++;
	  	}
	}
	//-k & -t 没有n || 只有 -t 
	if(flag[5]==1 && flag[2]==0){
		if(key<1){
			perror("-K Error");
			exit(1);
		}
		result = strcmp(array1[key-1],array2[key-1]);
	}
	//-k & -t & -n
	if(flag[4]==1 && flag[5]==1 && flag[2]==1){
		if(key<1){
			perror("-K Error");
			exit(1);
		}
		result = atoi(array1[key-1]) - atoi(array2[key-1]);
	}	
	 
	//-r
    if(flag[1]){
    	return result*-1;
	}
    return result;
}

void sortFile(const char *route,const char *outFile){
	//打开文件输入文件 
	FILE *fp;
	if(strcmp(route,"stdin")==0){
        fp = stdin;
    }else{
    	fp = fopen(route,"r");
	}
    
    if(fp == NULL){
    	perror("inFile Open Error");
    	exit(1);
	}else{
		printf("File open Success\n");
	}
	
	//读取文件 
	char buf[N][N];
	char hor=12;
	int n = 0;
	while(fgets(buf[n],N,fp)!=NULL){
		if(strcmp(buf[n],"EOF\n")==0){
			break;
		}
		n++;
		if(n>=N){
			printf("buffer overflow\n");
			break;
		}
	}
	fclose(fp);
//	for(int i=0;i<n;i++){
//		printf("%s",buf[i]);
//	} 
	
	//排序 
	qsort(buf,n,sizeof(buf[0]),cmp_string); 
	
	//输出
	printf("\nAfter sorted:\n");
	if(strcmp(route,"stdout")==0){
        fp = stdout;
    }else{
    	fp = fopen(outFile,"w");
	}
    
    if(fp == NULL){
    	perror("outFile Open Error");
    	exit(1);
	}else{
		printf("File open Success\n");
	}
	for(int i=0;i<n;i++){
		//-u
		if(flag[0] && i!=0){
			if(strcmp(buf[i],buf[i-1])==0){
				continue;
			}
		}
		fputs(buf[i],fp);
	} 
	
	fclose(fp);
}

int main(int argc,char *argv[]){
	printf("argc = %d\n",argc);
	char *outFile="stdout";
	//如果没有参数
	if(argc==1){
        sortFile("stdin",outFile);
        return 0; 
	} 
	//获取参数,做成假位图 
	
	memset(flag,0,10);
	/*
		char[0] : -u
		char[1] : -r
		char[2] : -n 
		char[3] :-o
		char[4] :-k
		char[5] : -t
		char[6] : -b
		char[7] : -f 
	*/
	
	const char *inFile = NULL;
	int skip=0;
	
	for(int i=1;i<argc;i++){
		//跳过-o后的参数(outFile) 
		if(skip==1){
			skip = 0;
			continue;	
		}
		if(strcmp(argv[i],"-u")==0){
			flag[0]=1;
		}else if(strcmp(argv[i],"-r")==0){
			flag[1]=1;
		}else if(strcmp(argv[i],"-n")==0){
			flag[2]=1;
		}else if(strcmp(argv[i],"-o")==0){
			flag[3]=1;
			skip=1;
			outFile =argv[i+1];
		}else if(strcmp(argv[i],"-k")==0){
			flag[4]=1;
			key=atoi(argv[i+1]);
			skip=1;
		}else if(strcmp(argv[i],"-t")==0){
			flag[5]=1;
			token = argv[i+1];
			skip=1;
		}else if(strcmp(argv[i],"-b")==0){
			flag[6]=1;
		}else if(strcmp(argv[i],"-f")==0){
			flag[7]=1;
		}else{
			inFile = argv[i];
		}
	}
	
	
//	for(int i=0;i<10;i++){
//		printf("%d",flag[i]);
//	}
//	printf("\n");
//	printf("%s\n",inFile);
	
	sortFile(inFile,outFile);
    return 0;
}

Afer sorted: 之前都是调试信息,不必在意
Afer sorted: 之后没有终端输出的,就是输出到 -o 的文件里了

运行效果:

./mysort -r a.txt -t ':' -k 3 -n -o b.txt

以':'分割成多个字段,按照第三个字段的数值大小,降序排序,输出到b.txt

./mysort a.txt -k 3 -r

按照第3个字符,降序排序

./mysort -u -b data.txt

忽略重复数据,忽略前导空格

./mysort -u -b -t ' ' -k 4 -r -f data.txt -o data.txt

忽略重复数据,忽略前导空格,以空格为分割符,取分割后的第四个域的数据为key,忽略大小写,降序排序,并将结果输出到原文件

https://gitee.com/cfqlovem-521/linux-sys-program1206/tree/master/lesson

posted @ 2021-09-27 22:11  191206  阅读(267)  评论(0编辑  收藏  举报