zoukankan      html  css  js  c++  java
  • Linux---more命令学习

    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 24
     5 #define LINELEN 512
     6 
     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("33[7m more?33[m");
    58     while((c = getchar()) != EOF)
    59     {
    60         if(c == 'q')
    61         return 0;
    62         if(c == ' ')
    63         return PAGELEN;
    64         if(c == '
    ')
    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 24
     5 #define LINELEN 512
     6 
     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("33[7m more?33[m");
    62     while((c = getc(cmd)) != EOF)
    63     {
    64         if(c == 'q')
    65         return 0;
    66         if(c == ' ')
    67         return PAGELEN;
    68         if(c == '
    ')
    69         return 1;
    70         
    71     }
    72     return 0;
    73 }

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

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

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

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

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

  • 相关阅读:
    api接口对于客户端的身份认证方式以及安全措施
    学SpringMVC
    Android用户界面设计:框架布局(转)
    Android与服务器端数据交互(转)
    用android LinearLayout和RelativeLayout实现精确布局(转)
    Android 源代码结构(转)
    Android开发在路上:少去踩坑,多走捷径(转)
    Map.EntrySet的使用方法
    利用JasperReport+iReport进行Web报表开发
    eclipse3.2 汉化 汉化包下载
  • 原文地址:https://www.cnblogs.com/r1chie/p/10795231.html
Copyright © 2011-2022 走看看