BUAA OS-Lab0
讲解部分梳理
Linux 基本操作
head
输出文件首部内容-n <n>
显示前 行内容-c <n>
显示前 个字节内容
tail
输出文件尾部内容-n <n>
显示末尾 行内容-c <n>
显示末尾 个字节内容-f
当文件增长时,输出后续添加的数据(适用于文件不断变化的情况,如日志文件)
ps
显示当前进程状态-aux / -ef
显示所有进程
mv
还可以用于重命名- 递归参数
-p
从指定目录向上级目录递归 eg 创建目录-r
从指定目录向其下级目录递归 eg 递归删除、拷贝
- 在命令后加上
&
符号,代表让命令在后台进行 Ctrl Q
进入块选模式,方便删注释和缩进- 选择之后可以通过
I
进入插入模式,方便段落缩进 {
}
向上/下选中 1 段
- 选择之后可以通过
Makefile 补充
-
开头最好写
.PHONY xx
(一般会写.PHONY:clean
).PHONY
后面跟的目标都被称为伪目标,对应的命令一定会被执行- 作用:避免伪目标同名文件冲突;提高执行效率
-
每一个指令 (command) 之前必须按一次制表符键来控制间隔,而不能是空格,否则 make 会报错
-
简洁高效的写法
# 使用变量维护Makefile # %.o: %.c 缩小编写量 CC = gcc OBJ = function.o test.o TARGET = test $(TARGET): $(OBJ) $(CC) $(OBJ) -o $(TARGET) %.o: %.c $(CC) -c $< -o $@
-
外层 makefile 调用内层 makefile
all: $(MAKE) -C subdir clean: $(MAKE) clean -C subdir
Git 补充
git branch
git branch <branch-name>
本地创建一个基于当前分支产生的分支。
git status
查看当前分支的状态,以及当前工作区的变动和暂存区的内容
git add
把一个新文件或者已经修改过的文件加入暂存区中
git add <file_name> # 将指定文件加入暂存区
git add . # 或使用.将项目所有文件加入暂存区(除.gitignore指定的文件外)
git restore
放弃修改(如果涉及到文件的增删,建议用 reset,用的时候慎重)
- 当文件还没有通过
git add
加入暂存区时,使用git restore <filename>
来撤销修改,使其退回到上一个 commit 的状态 - 如果文件已经加入了暂存区,通过
git restore **--staged** <filename>
来取消暂存。 - 其他错误回退命令
- 若文件未添加至暂存区:使用
git checkout <filename>
将文件替换成暂存区版本,或git checkout .
将工作区内的所有文件替换成暂存区内的文件(谨慎使用) - 若文件已添加到暂存区但未提交到本地仓库:使用
git reset HEAD .
撤销暂存区的所有修改至工作区,接下来就回到了上一步 - 若已提交到本地仓库:使用
git reset --hard HRAD^
将所有文件回退至上一版本
- 若文件未添加至暂存区:使用
git reset
git reset --hard
可以恢复文件的版本,既可以往旧版本恢复,也可以往新版本“恢复”。但–hard 是 reset 命令唯一的危险用法,使用时如果工作区的文件还未提交,git 会覆盖它从而导致无法恢复。所以使用时要小心谨慎
git checkout
切换分支
注意,在切换时,需要保证目前所有文件的状态均为“未修改”(没有修改过,或者已经提交)
git commit
使用 git commit -m <message>
这个命令将暂存区的修改提交到储存库中。当 message 参数有空格时需要把 message 用引号括起来
git rm
- 加
--cached
从暂存区删除,但不删除工作区文件,不加则两边都删
删除分支
git branch -d(D) <branch-name>
删除本地对应分支
git push origin --delete [branch_name]
删除远程分支
建立孤儿分支
git checkout --orphan <branch name>
创建孤立分支git rm -rf .
删除拷贝的所有文件touch add commit
git push -u origin <branch name>
创建远程分支并将其关联
提交空文件夹
Git 只对跟踪文件进行版本控制,而不跟踪文件夹本身。如果想要提交一个空文件夹到 Git 仓库中,可以在文件夹中添加一个占位文件,例如“.gitkeep”
合并分支
git merge
自动合并
- 如果自动合并不成功(存在冲突)
- 不想继续合并了,退出合并的中间状态
git merge --abort
- 处理冲突 最好在图形化界面上解决,更方便
git status
查看冲突的文件- 编辑冲突文件,解决冲突(记得删除三行分隔线)
git add 冲突文件
git commit -m "提交信息"
- 不想继续合并了,退出合并的中间状态
文本处理三剑客
grep 查找
grep [选项] PATTERN FIL
选项(常用):
-a 不忽略二进制数据进行搜索。
-i 忽略大小写差异。
-r 从目录中递归查找。
-n 显示行号
-q 安静模式,不打印结果
sed 替换、删除等
sed [选项] '命令' 输入文本
选项(常用):
-n:安静模式,只显示经过sed处理的内容。否则显示输入文本的所有内容。
**-i:直接修改读取的档案内容,而不是输出到屏幕。否则,只输出不编辑。
-E 选项用于启用扩展正则表达式,这样我们就可以使用更加灵活的正则表达式语法。**
命令(常用):
[行号]a[内容]:新增,在行号后新增一行相应内容。行号可以是“数字”,在这一行之后新增,
也可以是“起始行,终止行”,在其中的每一行后新增。当不写行号时,在每一
行之后新增。使用$表示最后一行。后面的命令同理。
[行号]c[内容]:取代。用内容取代相应行的文本。
[行号]i[内容]:插入。在当前行的上面插入一行文本。
[行号]d:删除当前行的内容。
[行号]p:输出选择的内容。通常与选项-n一起使用。
s/re(正则表达式)/string(/g):将re匹配的内容替换为string /g表示全文替换,不加则替换第一个
常用用法
awk '$1>2 {print $1,$3}' my.txt
# awk 'pattern action' file ,pattern 为条件,action 为命令,file 为文件
# 命令中出项的 $n 代表每一行中用空格分隔后的第 n 项
# 该命令的意义是文件 my.txt 中所有第一项大于 2 的行,输出第一项和第三项
awk -F, '{print $2}' my.txt
# -F 选项用来指定用于分隔的字符,默认是空格
# 该命令的意义是打印用 , 分隔后的第 2 项
grep -n "all" my.txt > result.txt
# 打印含有“all”的行并显示行号
sed -i "s/$2/$3/g" $1
# 将传入的第一个参数(文件)里的所有 第二个参数 替代为 第三个参数
shell 编程注意
-
首句
#!/bin/bash
-
等号与运算符两边不允许有空格,
-op
的两边与[]
内部两边必须有空格 -
获取变量值建议使用
${var}
,花括号避免歧义 -
引用变量必须在双引号中进行
-
$#
传递的参数个数;$*
一个字符串,内容是传递的全部参数 -
let
赋值运算 eglet i=i+1
等价于i=$(($i+1))
(双括号是计算值) -
流程控制
if [ 表达式1 ]; then 命令列表1; elif [ 表达式2 ]; then 命令列表2; else [ 表达式3 ]; then 命令列表3; fi
while [ 表达式 ];do 命令列表; done for name in [参数列表];do 命令列表; done #最后都有done
Lab0
踩坑
在评测前先确保自己对于文件的变更已经全部添加到暂存区(使用合适的 git add
和 git commit
)!!注意先add
再commit
,新建的文件需要先添加跟踪才会到暂存区,才能用commit
提交。
- 整型转字符串
sprintf
int n; scanf("%d",&n); char str[20]; sprintf(str,"%d",n); printf("%s",str)
- 三剑客不熟悉
- 变量使用忘了
自增操作! #错误写法 a=a+1 #正确写法 a=$[$a+1]
- 在 sed 命令中
- 使用变量时,正则用双引号(一般只能用单引号)
#!/bin/bash name=tomas sed -i "s/rose/${name}/g" name.txt
- 单引号
‘’
- 括起来的字符均作为普通字符出现
- 双引号
“”
- 括起来的字符除
$
、\
、‘’
、和“”
之外都将作为普通字符对待,所以如果要用变量值就要用“”
- 括起来的字符除
- 倒引号````
用于命令替换,其所括字符串在被 Shell 解释时,首先执行其中的命令并将其结果代替该命令 - 俩小括号 / 俩小括号/ 俩小括号/中括号计算结果替换,$单小括号执行结果替代
- 单引号
- 要更改源文件内容要加参数
-i
# 替换字符串,并更改原文件内容 # 在sed后面加 -i,即编辑文档“edit files in place”选项
- 使用变量时,正则用双引号(一般只能用单引号)
- gcc 编译时如果头文件不在
/usr/include
里,一定记得-I <头文件所在位置路径>
难点分析
Linux 下命令种类多,参数复杂
ls
、mv
、touch
等常用命令倒是能熟练掌握,但像sed
、awk
等参数复杂功能复杂的命令,在使用时就容易一下想不起来正确的使用方法- 解决方法:先通过多练习熟练,使用时若不确定先查阅资料或参考书
shell 编程中符号和空格使用非常容易出错
比如
- 各种引号的使用
- 单引号
‘’
括起来的字符均作为普通字符出现 - 双引号
“”
括起来的字符除$
、\
、‘’
、和“”
之外都将作为普通字符对待,所以如果要用变量值就要用“”
- 倒引号````
用于命令替换,其所括字符串在被 Shell 解释时,首先执行其中的命令并将其结果代替该命令
- 单引号
- 各种括号的使用
$(())
/$[]
计算结果替换,$()
执行结果替代
- 空格的使用
- 等号与运算符两边不允许有空格,
-op
的两边与[]
内部两边必须有空格
- 等号与运算符两边不允许有空格,
Makefile 嵌套
- makefile 嵌套的写法有很多,用
$(Make) -C subdir
(-C
是跳转到指定路径再执行 make 操作) 或者cd subdir && make
都可以,需要特别注意不要用混了 - 用
$(Make)
这种操作时想要做 make clean,是$(MAKE) clean -C subdir
gcc
编译时如果依赖的库文件不在本文件夹下,要记得用-I
进行链接- 注意相对路径和绝对路径的使用要准确
体会
编写 Shell 脚本和 make 文件时熟练度至关重要
虽然上学期学习了系统编程,有了一定的编写 Shell 脚本和 make 文件的基础。但由于课后自主训练较少,加上假期疏于复习,导致对相关操作并不完全熟练。但 Shell 脚本和 make 文件的编写是在 Linux 环境下顺利进行实验的基础,因此需要在课后多多练习,尽快熟悉相关操作,以免后续实验中因基础操作不熟练浪费时间
debug 时利用好讨论区 & 利用好git
操作
Excecise1 测评错误后,一直以为是自己哪里写错,反复检查每个文件,提交了 4、5 次,折腾了快 2 个小时还是错误。后来用git status
才发现是没有用git add
对新建的文件添加跟踪,导致一直没能把这部分文件成功提交 😢
后来在看讨论区时,更是发现一篇精华帖的开头就用大写加粗强调了这个问题……
exam 前准备
血泪教训
- 在 bash 中,整个程序的返回值
?
=
最后一条语句的返回值
?=最后一条语句的返回值
?=最后一条语句的返回值?;且在评测机中一旦程序的返回值$?为 1,它就认为这个程序报错了;
故最好在每一个脚本文件末尾都手动写一个exit 0
$?
表示上一条语句的返回值;$#
表示传参个数
不熟操作
- 输出 hello.c 中所有包含“os_hello”(区分大小写)的行的“os_hello”(区分大小写)以左的内容,如果一行出现多个,则输出第一次出现以左的部分
grep
&sed
grep -E '.*os_hello' hello.c | sed -E 's/(.*)os_hello.*/\1/'
awk
(两种均可)awk -F 'os_hello' '{print $1}' hello.c awk '/os_hello/ { sub(/os_hello.*/, ""); print }' hello.c
#var
是获取变量的长度,${#var}
获取长度值- 字符串切片操作
${variable:start:count}
表示从变量variable
的start
位置开始,截取count
个字符
坑
- 多层
if
容易忘记闭合fi
>>
追加会自动换行,想要不换行echo-n xx >> xx
$?
返回值为 0 表示上一条命令执行成功,1 表示执行失败
exam & extra 复盘
踩的坑(现场解决)
- 编写脚本文件时,想要输出文件内容,不能用 more 要用 cat
- more 是交互式的命令,一般在终端直接使用
知识漏洞(现场没解决)
- 书写条件判断语句时注意!debug 时优先检查条件判断是否出错!
- less than,应该是
-lt
不是-le
🥲
- less than,应该是
awk 用法补充
- awk + if
awk '{if($2=="'$PID'") print $3}' $FILE
if
语法和正常语法比较像,if()
后加空格,之后直接写命令(多为print
)
- 在 awk 中使用在 shell 中定义的变量
使用"'
把 shell 变量包起来,即"'$var'"
;注意是“双引号+单引号+shell 变量+单引号+双引号”的格式 - 将 awk 结果赋值给变量
使用倒引号,如var=`echo $result|awk '{print substr($result,16,3)}'