Linux开发环境及应用(大三下期末复习)

待到秋来九月八,我花开后百花杀
——黄巢《咏菊》

第二章 文本文件处理、正则表达式

匹配字符串a[i]=b[j]*c[k],等号和星号两侧可以有空格

a\[i] *= *b\[j] *\* *c\[k]

如何匹配任一非中括号字符

[^][]

匹配一对中括号及其之内的东西(这对中括号内部不能有中括号)

\[[^][]*]

如何匹配空行(只有空格)

^ *

第三章 文件系统

find 三板斧:范围、条件、动作。

范围
一棵或多棵目录树

条件
-name 文件通配符 切记文件通配符两侧引号,避免shell手快进行文件名展开。匹配规则是要传进find程序的,因为不单单要在本目录下找,可能还要递归的找。
-regex 正则表达式 带路径的
-type f普通文件 d目录 l符号链接文件 c字符设备文件 b块设备文件 p管道文件
-size +n单位 -size -n单位 单位有c字符b块kMG默认是b,b是512字节
-mtime +n -n
-newer filename
动作
-print 打印路径+文件名
-exec xxxxxx {} \; 执行某一命令
-ok 与-exec的区别是对每一个符合条件的{}执行操作前都进行询问

解释命令:find . -type d -print

从当前目录开始查找,找到所有目录并打印出路径

解释命令:find / -name “stud*” -type d -print

从当根目录开始查找,满足名字是stud开头的目录并打印出路径(两个条件是“与”的关系,且-name后的星号是文件通配符不是正则的元字符)

解释命令:find / -type -f -mtime -10 -print

从根目录开始查找,满足名字是stud开头的目录并打印出路径(两个条件是“与”的关系,且-name后的星号是文件通配符不是正则的元字符)

解释命令:find . ! -type d -link +2 -print

从当前目录查找,类型不是目录,且link数大于2的文件,打印路径

解释命令:find . -size +100k \( -name core -o -name ‘*.tmp’ \) -print

此句*.tmp 的两侧使用单双引号均可
*前可用\转义,()前也可用\转义
从当前目录开始查找,满足条件1.大小大于100k 2.名字是core或以.tmp结尾的文件,打印路径

find /lib /usr -name ‘libc*.so’ -exec ls lh {} \;

find src -name \*.c -exec frep -n — –help {} /dev/null \;

find . -type d -exec sh -c '[ -f "1"/README ] || touch "1"/README' _ {} \;

递归地在所有子目录下添加 README 文件(如果该目录下还没有 README)

find . -type d -exec sh -c '[ -f "1"/README ] || echo "# Directory:1" > "$1"/README' _ {} \;

添加内容到 README,比如写一句话或模板

find . -type f -name ‘README.md’ -delete

递归地删除所有子目录下的 README.md(无论是否存在内容)

find . -name CVS –exec rm –rf {} \; 和 find . -name CVS -print | xargs rm –rf哪个会成功、哪个会失败?

xargs可以将标准输入构造为命令的命令行参数,如果太多,可自动分批。且可以使用xargs的-n选项手动指定每批处理多少个。

rm -f .dat 文件名.dat展开失败可能的原因是什么?有什么代替命令

ls | grep “.dat$” | xargs rm -f

ls的选项:-F(早期终端没颜色时如何区分列出的是——目录/?可执行文件*?符号链接文件@?普通文件-l(等价于ll)-h(把大小转换成人可读的单位,字节数-> K或M什么的)

  • ls 和 ls * 的区别

ls 列出当前目录下的所有文件和目录。
* 代表当前目录下的所有文件和目录,ls * 列出当前目录下的所有文件(不包括目录)以及当前目录下所有目录中的内容。

  • ls -l 和 ll 的区别

如果设置了set -x,或者输入命令alias查看系统已经设置的全部别名,就会发现,ll是ls -l的别名,没有区别
# ll
+ ls –color=auto -l –color=auto

  • ls -ld 目录名 的输出是什么

该目录本身的信息,如果没有d,输出的就是目录内部的文件

当前工作目录是进程的一部分,命令:pwd打印当前目录,cd改变当前目录

  • cd后面什么都不加会发生什么?

回到用户主目录

  • 内部命令 vs 外部命令

内外是相对shell来说的,shell接收到操作员输入的一行字符串后,进行一系列加工(通配符展开)过后,最左边的单词看作命令的名字。如果这个命令是shell自己决定的,那么就是内部命令。如果需要去磁盘找可执行文件,是外部命令。
例如,cd是shell的内部命令,ls是外部命令。

mkdir, -p自动创建,rmdir

rmdir 与 rm -r 的区别

rmdir只能删除空目录(里面只能有. 和 ..),所以不怎么用。
rm -r是常用的,-r是递归的意思,把子子孙孙都删除

cp -r dir1 dir2 如果dir2存在/不存在,分别发生什么

存在:dir2新建子目录dir1,把dir1里的内容复制到dir2/dir1中
不存在:新建dir2,把dir1里的内容复制到dir2中

cp -v 冗长,了解进度
cp -u 根据时间戳增量拷贝,用于备份更新。好处:快;如果dir1和dir2写反了不会灾难
touch 修改时间戳

命令如何获取信息?硬编码是不可取的。

  • 配置文件
    • 分为:系统级偏好配置,例如bash的/etc/profile
    • 用户级偏好配置,~/.bash_profile)
  • 环境变量
    • 获取的方式:getenv
  • 命令行参数
    • 三种风格
    • (dd风格)dd if=sysdisk.img of=/dev/sdb
    • (find,gcc风格) gcc -O0 -Wall -g -masm=intel -Wa,-ahl -c shudu.c
    • (ls风格,长选项和短选项)–width=80 或 -w80
  • 交互式键盘输入
    • 这种方式在Linux命令中极少使用

STICKY权限(粘着位)能解决什么问题?

目录有写权限并且带STICKY属性,此目录下的文件仅文件主可以删除,其他用户删除操作会失败

第四章 bash脚本

脚本文件的执行有几种写法?有什么区别?

  • 三种新建子shell的执行方式:
    • bash<脚本名 (不可携带参数,其他都可携带参数)
    • bash 脚本名
    • ./脚本名(需先给脚本添加x权限,chmod u+x 脚本名)
  • 两种在当前进程中执行:
    • . 脚本名
    • source 脚本名

输入重定向符号<、<<和<<<的区别是什么

一个<:用法为 “命令 < filename”,把filename这个文件当作stdin
两个:用法为 “命令 << 定界符”,接下来可连续输入多行,直到再次遇到定界符,把这几行作为输入给到命令。其中可以使用反撇号做变量替换
三个:用法为“命令 <<< 内容”,只会取得第一个单词作为输入内容给到命令

输出重定向> >> 2>的区别是什么?

> filename 先清空(覆盖)
>> filename 追加
2> 把输出到2号文件(stderr)的内容重定向
分离stdout和stderr的意义是,程序运行时的输出可以重定向到文件,而运行过程中出现的错误可打印到屏幕上,给操作员看。如果非要把两个放一起,可以使用2<&1

我想用gcc a.c -o a > try.err 来把编译时输出的错误重定向到try.err,为什么没效果?

要使用gcc a.c -o a 2> try.err,或者 gcc a.c -o a > try.err 2>&1
但不能写为gcc a.c -o a 2>&1 > try.err

如果想使用 | more 把gcc输出的错误分屏显示,怎么办?

要使用gcc a.c -o a 2>&1 | more

在c语言程序中输出到文件时一定要先打开文件再输出吗?能不能直接指定一个数当作文件描述符?

可以。分为两种情况:
一是0,1,2是固定的,可直接使用
二是如果在运行c程序时在命令行使用“./可执行文件 5< a.txt”那么在c程序内无需打开5号文件,运行完毕后直接打开a.txt查看结果即可。注意5的后面没有空格。

引用bash变量addr的方式有{addr}和addr,区别是什么

当想拼接时,只能用${addr}AAA

当在shell中引用未定义变量时默认为空串,这很坏了,怎么使之产生一个错误?

set -u。如果取消设置即为set +u

一般情况下当前环境变量 PATH 不包括当前目录,原因何在?

在命令的组合使用中,用{}和()的区别是什么?

1.()启动子shell,{}在当前shell执行。最显著的现象就是如果有cd,那么()后当前目录不变,而{}后当前目录改变
2.()是元字符,而{}不是,是命令。所以(后可不加空格,而{后必须加空格。
3.分号的区别(1;2){1;2;} 多行可不写分号,捏成一行时要注意{后的空格和}之前的分号

第五章 进程

编写 C 语言程序,使用与下列 shell 命令相同的机制完成同样的功能
sort < aaa.txt > bbb.txt

思路:0 dup到 aaa.txt,1 dup到 bbb.txt

int main(){
    int sv;
    if (fork() == 0) {
        int fd1 = open("aaa.txt", O_RDONLY);
        dup2(fd1, 0);
        close(fd1);
        int fd2 = open("bbb.txt", O_CREAT | O_WRONLY, 0666);
        dup2(fd2, 1);
        close(fd2);
        execvp("sort");
        exit(-1);
    }
    wait(&sv);
}

编写 C 语言程序,使用与下列 shell 命令相同的机制完成同样的功能
cat aaa.txt | grep — –help

思路
进程A:执行cat aaa.txt,标准输入 -> 不变;标准输出->管道入口
进程B:执行grep — –help,标准输入 -> 管道出口;标准输出-> 不变
父进程:什么都不做

int main()
{
        int fd, sv;
        pipe(fd);
        if (fork() == 0) {
            dup2(fd[1], 1);
            close(fd[1]);
            close(fd[0]);
            execlp("cat", "a.txt", 0);
            exit(1);
        } else if (fork() == 0) {
            dup2(fd[0], 0);
            close(fd[0]);
            close(fd[1]);
            execlp("grep", "--", "--help", 0);
            exit(1);
        }
        close(fd[0]);
        close(fd[1]);
        wait(&sv);
        wait(&sv);

(样题)
编写 C 语言程序,使用与下列 shell 命令相同的机制完成同样的功能
ps -ef > proc.list; grep root < proc.list

思路
进程A:执行ps -ef,标准输入 -> 不变;标准输出->proc.list
父进程:等待进程A执行完毕后,执行grep root,标准输入 -> proc.list;标准输出 -> 不变

int main()
{
    int sv;
    if (fork() == 0) {
        int fd1 = open("proc.list", O_CREAT | O_WTONLY, 0666);
        dup2(fd1, 1);
        close(fd1);
        execlp("ps", "-ef", 0);
        exit(1);
    }
    wait(&sv);
    int fd2 = open("proc.list", O_RDONLY);
    dup2(fd2, 0);
    close(fd2);
    execlp("grep", "root", 0);
}

(上机作业四)
编写 C 语言程序,使用与下列 shell 命令相同的机制完成同样的功能
grep -v usr < /etc/passwd | wc –l > r.txt; cat r.txt

思路
进程A:执行grep -v usr,标准输入 -> /etc/passwd;标准输出->管道入口
进程B:执行wc –l,标准输入 -> 管道出口;标准输出-> r.txt
父进程:等待两个进程都执行完毕后,执行cat r.txt