Linux程序开发(二):Linux文件处理命令和正则表达式

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊!

喜欢我的博客的话,记得点个红心❤️和小关小注哦!您的支持是我创作的动力!数据源存放在我的资源下载区啦!

Linux程序开发(二):Linux文件处理命令和正则表达式

第二次作业

1. 文本处理命令(grep cut sort wc diff cmp)和正则表达式

  1. 显示/etc/locale.gen中以’zh’开头的行。
grep '^zh' /etc/locale.gen

== grep:表示进行文本搜索的命令。
== '^zh':是一个正则表达式,^ 表示匹配行的开头,zh 表示以 'zh' 开头。
== /etc/locale.gen:是要搜索的文件路径。
  1. 显示/etc/passwd文件中是’/bin/bash’结尾的行。
grep -v '/bin/bash$' /etc/passwd

== -v 选项来获取不匹配模式的行
== 并使用 $ 来匹配以 /bin/bash 结尾的行。
  1. 将/etc/group中的数字单独列出。
grep -o '[0-9]\+' /etc/group

==  -o 选项来只输出匹配的部分
==  使用正则表达式 [0-9]\+ 来匹配一个或多个数字。
  1. 列出netstat -ant命令结果中出现端口为22(:22)的行。
netstat -ant | grep ':22'

== netstat -ant 命令来获取网络连接信息
== 然后使用管道将输出结果传递给 grep 命令
== grep 命令使用正则表达式 :22 来匹配包含端口为 22 的行。
  1. 配合cut命令查看/etc/passwd,只显示系统中的用户名、UID、GID。

提示:

passwd文件每行数据:

root:x:0:0:root:/root:/bin/bash

解释:

用户名:密码:UID(用户ID):GID(组ID):描述:主目录:缺省Shell

cut -d: -f1,3,4 /etc/passwd

== 使用 -d 参数指定字段分隔符为冒号 :,
== 然后使用 -f 参数指定要提取的字段 —— 1、3 和 4 分别对应用户名、UID 和 GID。
  1. 利用wc命令,通过/etc/passwd文件计算系统中的用户总数。
cat /etc/passwd | wc -l

== 使用 cat 命令来将 /etc/passwd 文件的内容输出到标准输出,
== 然后使用管道将输出结果传递给 wc 命令。
== wc -l 用于计算输入行数。
  1. 列出/etc/passwd中的root用户(UID=0的用户)。要显示出root用户的所在整行。
grep '^root:' /etc/passwd

==  ^root: 来匹配以 "root:" 开始的行,其中 "^" 表示行的开头。
== 由于每行的格式是用冒号分隔开的,因此只需匹配以 "root:" 开始的行即可找到 root 用户的相关信息。
  1. 根据UID的大小,降序排列/etc/passwd中行并显示。要显示整行数据。
sort -t: -k3nr /etc/passwd

== -t: 来指定冒号为字段分隔符,
== -k3nr 表示按照第 3 个字段(即 UID)的数值进行降序排序。
== -k3nr 中的 -k 表示设置排序的键(key),后面紧跟着指定键的规范。
== 3 表示选择第 3 个字段作为排序键。
== n 表示将该字段以数字方式进行排序。
== r 表示将排序结果反转,实现降序排列。
  1. df命令可以查看各个挂载区的利用率,请按利用率(已用%)从大到小排列,并显示。
df -h | awk '{if ($NF != "/snap/core") print $0}' | sort -k 5 -r

== df -h:执行 df -h 命令,显示当前系统中所有已挂载文件系统的使用情况。
== -h 参数指定显示结果为人类可读形式,方便快速浏览。
== awk '{if ($NF != "/snap/core") print $0}':使用 awk 命令过滤掉 /snap/core 目录,
== sort -k 5 -r:使用 sort 命令对其按照第五列(即利用率)进行降序排列(-r 参数表示按照降序排列)。
== -k 5 参数指定要对第五列进行排序。
  1. last命令可以查看最近登录的主机ip,请按ip进行统计并显示。*选做

提示:统计时可以采用uniq -c命令

uniq命令读取输入文件,并进行比较,第二个及以后更多个重复行将被删去。

-c参数:输出时,在每行行首加上该行在文件中出现的次数。
last | awk '{print $3}' | sort | uniq -c | sort -nr

== last:执行 last 命令,显示最近登录的用户列表和登录记录。
== awk '{print $3}':使用 awk 命令提取每行的第三列,对应登录记录中的IP地址。
== sort:将提取出的IP地址进行排序。
== uniq -c:使用 uniq 命令统计每个IP地址出现的次数,并在输出结果前面加上计数。
== sort -nr:将统计结果按照计数从大到小排序。
  1. 统计字母出现次数。*选做

英文诗:

The seasons
Spring is gay with flower and song
Summmer is hot and days are long
Autumn is rich with fruit and grain
Winter brings snow and the New Year again

将上面英文诗写入文件seasons.txt中,然后计算每个字母出现的次数,大小写不区分。

提示:统计时可以采用uniq -c命令

cat seasons.txt | grep -o '[a-zA-Z]' | tr '[:upper:]' '[:lower:]' | sort | uniq -c

== cat seasons.txt:使用cat命令读取seasons.txt文件的内容。
== grep -o '[a-zA-Z]':使用grep命令和正则表达式[a-zA-Z]来匹配并输出文本文件中的所有字母字符。
== -o参数表示只输出匹配到的部分。
== tr '[:upper:]' '[:lower:]':使用tr命令将所有大写字母转换为小写字母,以便在统计时不区分大小写。
== sort:对字母进行排序,以便相同字母在一起。
== uniq -c:使用uniq命令统计每个字母出现的次数,并在输出结果前面加上计数。
  1. 读取上面seasons.txt文件,寻找大写S开头的行。
grep '^S' seasons.txt

== grep '^S':使用grep命令和正则表达式^S来匹配并输出文本文件中以大写字母"S"开头的行。
== ^表示以指定字符开头。
  1. 读取上面seasons.txt文件,寻找a开头(不区分大小写)的单词。
grep -oiw '^a[a-z]*' seasons.txt

== grep -oiw 'a[a-z]*':使用grep命令和正则表达式a[a-z]*来匹配并输出文件中以字母"a"开头(不区分大小写)的单词。
== -o参数表示只输出匹配到的部分
== -i参数表示不区分大小写
== -w参数表示匹配整个单词。
  1. 读取上面seasons.txt文件,寻找f或者s开头(不区分大小写)的单词。
grep -oiwE '(f|s)[a-z]*' seasons.txt

== -o参数表示只输出匹配到的部分
== -i参数表示不区分大小写
== -w参数表示匹配整个单词
== -E参数表示使用扩展正则表达式。
  1. 文件data.txt中数据:*选做
叶湘伦 13888888888 330301200109090017 yxl@test.com 2023-08-08 5000.45
路小雨 18966666666 220101200210110023 lxy@test.com 2023-08-09 4800.88

data.txt

请匹配文本中的电话号码、身份证号码、邮箱、日期。

电话号码:

grep -E -o '\b1[3-9][0-9]{9}\b' data.txt

== \b 表示单词边界,避免误匹配
== 1 代表手机号码开头必须为1
== [3-9] 代表手机号码第二位可以为3-9中的任意一个数字
== [0-9]{9} 代表手机号码后面9位必须是数字

身份证号码:

grep -E -o '[1-9][0-9]{5}(19|20)[0-9]{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9Xx]' data.txt

== [1-9][0-9]{5} 表示身份证号码前6位地址码,第一位不能为0
== (19|20) 表示年份必须是19或20开头
== [0-9]{2} 表示年份后两位数字
== (0[1-9]|1[0-2]) 表示月份,01-12月
== (0[1-9]|[12][0-9]|3[01]) 表示日期,01-31日
== [0-9]{3} 表示生日后面的顺序码,可以是任意数字
== [0-9Xx] 表示最后一位是数字或者字符 X 或 x

邮箱:

grep -E -o '\b1\d{10}\b|\b\d{17}[\dXx]\b|\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b|\b\d{4}-\d{2}-\d{2}\b' data.txt

== \b 表示单词边界,避免误匹配
== 1\d{10} 表示国内手机号码,开头必须为1,后面10位必须是数字
== \d{17}[\dXx] 表示身份证号码,前面17位必须是数字,最后一位是数字或字符 X 或 x
== [A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,} 表示邮箱地址,包含一个或多个字母、数字、下划线、点、百分号、加号、减号的组合,接着是 @ 符号,然后是一个或多个字母、数字、点、减号的组合,最后是一个点和两个或更多的字母(例如 .com、.cn 等)
== \d{4}-\d{2}-\d{2} 表示日期,格式为 YYYY-MM-DD

日期:

grep -E -o '[0-9]{4}-[0-9]{2}-[0-9]{2}' data.txt

== [0-9]{4} 表示年份,必须是4位数字
== -[0-9]{2}- 表示月份和日期,必须是2位数字
== 最终得到的模式为 YYYY-MM-DD

2. 下图为Linux系统目录树结构的一部分。

  1. 用户gdufe与用户root的家目录在哪里?
用户gdufe的家目录在:	/home
用户root的家目录在:	/
  1. 若当前工作目录是/home/gdufe,请给出目录mike、usr的相对路径与绝对路径。
mike的相对路径:	../mike,
		绝对路径:	/home/mike
usr的相对路径:	../../usr,
		绝对路径:	/usr

3. 编程题

  1. 汉诺塔(Tower of Hanoi),是一个源于印度古老传说的益智玩具。大天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大天命令婆门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

请用C语言采用解决汉诺塔问题。

三根柱子分别用’A’,‘B’,'C’表示。

输入:盘子数。输出:移动步骤。

例如:

输入:3

输出:

A->C
A->B
C->B
A->C
B->A
B->C
A->C
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void hanoi(int n, char from, char to, char aux) {
    if (n == 1) {
        printf("%c->%c\n", from, to);
    }
    else {
        hanoi(n - 1, from, aux, to);   // 将 n-1 个盘子从 from 移动到 aux,使用 to 作为辅助柱子
        printf("%c->%c\n", from, to);  // 将最大的盘子从 from 移动到 to
        hanoi(n - 1, aux, to, from);   // 将 n-1 个盘子从 aux 移动到 to,使用 from 作为辅助柱子
    }
}

int main() {
    int num;
    printf("请输入盘子数:");
    scanf("%d", &num);
    printf("移动步骤:\n");
    hanoi(num, 'A', 'C', 'B');  // 将 num 个盘子从柱子 A 移动到柱子 C,使用柱子 B 作为辅助柱子
    return 0;
}

代码结果:

在这里插入图片描述

  1. 用C语言输出n以内的素数。速度越快越好!

输入:n。输出:依次输入n以内的素数。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int is_prime(int n) {
    if (n <= 1) {
        return 0;
    }
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            return 0;
        }
    }
    return 1;
}

int main() {
    int num;
    printf("请输入一个正整数:");
    scanf("%d", &num);
    printf("2");
    for (int i = 3; i <= num; i += 2) {
        if (is_prime(i)) {
            printf(", %d", i);
        }
    }
    return 0;
}


代码结果:

在这里插入图片描述

  1. 编程程序,功能:删去一维数组中重复数,只保留一个,最后再输出。

用宏定义定义数组大小。

#define N 20

输入输出样例:

输入:

2 2 2 3 4 4 5 6 6 6 6 7 7 8 9 9 10 10 10 10

输出:

2 3 4 5 6 7 8 9 10

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdbool.h>

#define N 20

void remove_duplicates(int arr[], int* n) {
    int i, j;
    for (i = 0; i < *n; i++) {
        for (j = i + 1; j < *n;) {
            if (arr[j] == arr[i]) { // 检查是否有重复元素
                int k;
                for (k = j; k < *n - 1; k++) {
                    arr[k] = arr[k + 1]; // 删除重复元素
                }
                (*n)--;
            }
            else {
                j++;
            }
        }
    }
}

int main() {
    int arr[N];
    int n = 0;
    int num;
    bool input_success;

    printf("请输入一维数组元素(用空格分隔,最多%d个):", N);

    while (n < N && (input_success = (scanf("%d", &num) == 1))) {
        arr[n++] = num;

        char next_char = getchar();
        if (next_char == '\n' || next_char == EOF) { // 当输入回车换行或者遇到文件结尾时,跳出循环
            break;
        }
    }

    if (!input_success) {
        printf("输入错误!\n");
        return 1;
    }

    remove_duplicates(arr, &n);

    printf("去重后的数组为:");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

代码结果:

在这里插入图片描述

  • 29
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡林神不是猫

如果您觉得有帮助可以鼓励小卡哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值