More命令

more命令一般用于分页显示文件的内容,more会显示文件第一屏的内容,在屏幕的底部,more用反白字体显示文件的百分比,这时如果按空格键,文件下一屏内容会显示出来,如果按回车键,显示的则是下一行,如果输入“ q ”,则是结束显示。

more命令的几种用法

第一种:

$ more filename

显示文件filename的内容。

第二种:

$ command | more

将command命令的输出分页显示。

第三种:

$ more < filename

从标准输入获取要分页显示的内容,而这时more的标准输入被重定向到文件filename。

more命令的工作流程

+-----------> 显示24行

  |    +------> 输入操作,打印信息

  |    |           可以输入回车键、空格键、q键

|    +------> 输入回车键,打印一行

 +  ---------> 如果空格键,打印24行

        如果是q键  ---> 退出

more命令的编写---版本1

 1 #include <stdio.h>2 #include <stdlib.h>3 4 #define PAGELEN 245 #define LINELEN 5126 7 void do_more(FILE *);8 int see_more();9
10 int main(int ac,char *av[])
11 {
12
13     FILE *fp;
14     if(ac == 1)
15             do_more(stdin);
16     else
17         while(--ac)
18            if((fp = fopen(* ++av,"r")) != NULL)
19                {
20             do_more(fp);
21             fclose(fp);
22            }
23         else
24             exit(1);
25
26     return 0;
27 }
28
29
30 void do_more(FILE *fp)
31 {
32     char line[LINELEN];
33     int num_of_lines = 0;
34     int see_more(),reply;
35
36     while(fgets(line, LINELEN,fp))
37     {
38         if(num_of_lines == PAGELEN)
39         {
40             reply = see_more();
41
42             if(reply == 0)
43             break;
44
45             num_of_lines -= reply;
46         }
47         if(fputs(line,stdout) == EOF)
48         exit(1);
49
50         num_of_lines++;
51     }
52 }
53
54 int see_more()
55 {
56     int c;
57     printf("\033[7m more?\033[m");
58     while((c = getchar()) != EOF)
59     {
60         if(c == 'q')
61         return 0;
62         if(c == ' ')
63         return PAGELEN;
64         if(c == '\n')
65         return 1;
66
67     }
68     return 0;
69 }

fopen  打开文件,打开成功返回一个指向该文件的文件指针,失败返回NULL。

fgets  从指定的文件中获取数据,每次读一行,并存入指定的buffer中最多读size - 1个

fputs  把字符串输出到stram中,但不输出空字符。发生错误,则输出EOF

getchar 从标准输入获取一个字符,相当于getc(stdin)

more版本1的问题:

1.当屏幕上的文字上滚时,[ more ]字符也会随之上滚,

2.当我们按下空格或者 "q" 后,如果没有按下回车,程序没有任何反应。

自己编写的more命令分析

我们首先使用linux自带的more命令

$ ls /bin | more

很明显,我们想做的是将/bin 目录下的文件分页显示,在使用 “ | ”管道命令把 ls 的输出重定向到 more的输入,并且等待我们输入命令,结果是令人满意的。

我们再使用自己编写的more命令

$ls /bin | more_v1

发现和linux自带的more命令非常的不同,我们自己编写的more并没有等待我们输入命令,而是一溜烟全部显示出来了,那么到底是什么问题呢?

其实很简单,问题出在getchar这个函数上,这个函数是从标准输入中获取字符的,然而,我们ls命令的输出已经重定向到标准输入了,意味着getchar和ls共用一个数据流,所以我们自己编写的more命令才会没有等待我们输入命令,而一下子全部打印了出来。

关于流,网上有很多解释,我看了但是依旧不是太理解,我自己画了一个图,也表达了我对流的理解,一个文件与另一个文件进行数据的传输,我认为这就是一个流。共用一个流就是两个文件都与一个文件同时传输数据。

这下找到了问题的根源,也就是说getchar不适用与more命令中,我们需要更改more。意味着我们需要把getchar的输入换成一个独立的流,

more命令的编写---版本2

 1 #include <stdio.h>2 #include <stdlib.h>3 4 #define PAGELEN 245 #define LINELEN 5126 7 void do_more(FILE *);8 int see_more(FILE *);9
10 int main(int ac,char *av[])
11 {
12
13     FILE *fp;
14     if(ac == 1)
15             do_more(stdin);
16     else
17         while(--ac)
18            if((fp = fopen(* ++av,"r")) != NULL)
19                {
20             do_more(fp);
21             fclose(fp);
22            }
23         else
24             exit(1);
25
26     return 0;
27 }
28
29
30 void do_more(FILE *fp)
31 {
32     char line[LINELEN];
33     int num_of_lines = 0;
34     int reply;
35     FILE *fp_tty;
36     fp_tty = fopen("/dev/tty","r");
37     if(fp_tty == NULL)
38     exit(1);
39
40     while(fgets(line, LINELEN,fp))
41     {
42         if(num_of_lines == PAGELEN)
43         {
44             reply = see_more(fp_tty);
45
46             if(reply == 0)
47             break;
48
49             num_of_lines -= reply;
50         }
51         if(fputs(line,stdout) == EOF)
52         exit(1);
53
54         num_of_lines++;
55     }
56 }
57
58 int see_more(FILE *cmd)
59 {
60     int c;
61     printf("\033[7m more?\033[m");
62     while((c = getc(cmd)) != EOF)
63     {
64         if(c == 'q')
65         return 0;
66         if(c == ' ')
67         return PAGELEN;
68         if(c == '\n')
69         return 1;
70
71     }
72     return 0;
73 }

第二个版本中使用了  /dev/tty 这个设备文件,向这个文件写相当于显示在用户的屏幕上,向这个文件读相当于从键盘中获取用户输入。这样我们的程序就拥有两个流, “ls” 的输出,将其分页显示到屏幕上,当more需要用户输入时,从 /dev/tty得到数据。

第二个版本仍然有more字符被打印到输出上、按下空格或者Q键还需要额外按下回车、无法根据中断大小来决定显示行数、无法文件已显示的百分比,这些问题有涉及到与终端类有关,我暂时读到这里,以后慢慢补充

-----------------上文在 2019/4/30 记录-------------------

本篇笔记自拜读《 Unix/Linux编程实践教程》

我也推荐和我一样的初学者去拜读这本书,让你对linux有可下手的地方。

Linux---more命令学习相关推荐

  1. linux基础命令学习笔记(二)

    linux基础命令学习笔记(二) 1.kill :终止进程  kill pid (唯一标示一个进程) kill -9  强制终止  kill -15 命令未结束不能终止 # ps aux 查看所有进程 ...

  2. linux账户密码 群组放在,linux基础命令学习(四)用户与群组

    一.linux用户账号的管理 linux用户账号的管理主要包括用户添加.用户删除.用户修改. 添加用户账号就是在系统创建一个新账号,然后为新账号分为用户号.用户组.主目录和登录Shell等资源. 刚添 ...

  3. Linux基础命令学习——方法二(给swap分区增加500M)

    在之前的博客中也有相关介绍,将Swap分区扩展500M,当然有很多方法,今天来记录第二种方法. 上篇介绍swap分区扩展500M的方法: Linux基础命令学习--实战篇(给swap分区增加500M) ...

  4. linux命令cp建立硬链接,Linux cp命令学习

    linux命令是对Linux系统进行管理的命令.对于Linux系统来说,无论是中央处理器.内存.磁盘驱动器.键盘.鼠标,还是用户等都是文件,Linux系统管理的命令是它正常运行的核心,与之前的DOS命 ...

  5. 【Linux学习】Linux free 命令学习

    一.学习这个命令的背景 因为最近Gitlab服务器占用内存很多,也在下面的这篇博客里面写了怎么减少Gitlab占用的内存问题. +[Git学习]解决GitLab内存消耗大的问题 但是一开始并没有很清楚 ...

  6. (初学入门足够)Linux终端命令学习——在VMware虚拟机中创建的ubuntu(Linux最常用的发行版本)

    目录 前言 学习Linux终端命令的原因 学习Linux终端命令的技巧 Linux常用命令 一.常用linux命令的基本使用 1.查看目录内容 1.1 ls 列表和隐藏文件显示 1.2 ls 通配符的 ...

  7. Linux dmesg 命令学习

    /proc文件系统     在 /proc 文件系统中,对虚拟文件的读写操作是一种与内核通信的手段,要查看内核回环缓冲区中的消息,可以使用 dmesg 工具(或者通过 /proc 本身使用 cat / ...

  8. linux (ubuntu) 命令学习笔记

    1, md5sum 输出字符串的MD5值 echo -n 123456 | md5sum //-n表示不打印回车符 2, ubuntu设置dock任务栏鼠标点击效果 16.04: 调整位置:gsett ...

  9. Linux常用命令学习大全

    Linux常用命令大全 窍门:Ctrl+F 快速查找Linux命令(为了方便查看,下面的每个标题都可以点击收缩) Linux命令 - 系统信息 命令代码 注释说明 arch 显示机器的处理器架构(1) ...

  10. Linux 常用命令 学习笔记

    1.创建目录: //创建目录filetest mkdir filetest 2.创建子目录: //创建子目录filetestchild mkdir -p filetest/filetestchild ...

最新文章

  1. iOS UITextField输入框随键盘弹出界面上移
  2. Java中集合中根据对象的某个属性去重
  3. 动手学PaddlePaddle(5):迁移学习
  4. linux的基础知识——会话
  5. python 连续三个数满足条件_计算满足条件的连续值数(Pandas Dataframe)
  6. ServiceComb中的数据最终一致性方案
  7. 2022年企业微信生态研究报告
  8. 查看 linux 网络状态命令,Linux操作系统常用的网络状态查询命令
  9. 科学计算机的用途,计算机最主要的用途之一就是科学计算,科学计算可分为两类...
  10. Linux下autoconf与automake
  11. 快速在指定文件夹打开命令行
  12. 学计算机的是不是都非常木讷,北大学神韦东奕​是正常人吗?内向木讷是缺点​,拿不出手?​...
  13. Python进行vivo手机评论数据信息情感分析、LDA主题分析
  14. Java @Min(0)的意义
  15. 滚动轴承损伤、偏翘、电蚀、跑外圈特征分析及信号特征提取
  16. 学习深度学习是否要先学习机器学习?
  17. CSS:设置边框和背景
  18. Day-8 bootstrap 徽章、进度条、分页、列表组
  19. 破解flashFXP密码全过程
  20. Javascript 元素拖曳操作 By shawl.qiu (兼容IE,Opera,Firefox)

热门文章

  1. 晶圆测试中的pinforce
  2. 神经网络注意力机制可视化,人工神经网络可视化
  3. Unity Shader 学习笔记(27)渲染轮廓线(描边)方法、卡通风格渲染、素描风格渲染
  4. 台湾大学林轩田《机器学习基石》学习笔记第6讲——Theory of Generalization
  5. 书柜板子厚度如何去选择
  6. EXCEL 将列内容,逆序粘贴
  7. 运维和网工的差别,跟你们说一说
  8. 【文件缺失/被隐藏】三种递进式方法寻找文件(有点新奇)、丢失文件填补方法(etc/host文件‘丢失’为例)
  9. LeetCode_962_Maximum Width Ramp
  10. Java中POJO、VO、DTO、PO、Entity的区别