Part1. 思考题

Thinking 0.1 Git相关

执行以下命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
cd ~/learnGit # 已初始化的git仓库
touch README.txt
git status > Untracked.txt
# 显示 README.txt 是一个未被跟踪的文件

# 2. 执行 git add README.txt
echo "This is the README file for learnGit." > README.txt
git add README.txt
git status > Stage.txt
# 显示 README.txt 是一个已暂存的文件,Untracked.txt 是一个未被跟踪的文件

# 3. 提交 README.txt 文件
git commit -m "23373446"

# 4. 对比 Untracked.txt 和 Stage.txt 的结果
cat Untracked.txt
cat Stage.txt
# Untracked.txt 显示 README.txt 是一个未被跟踪的文件,Stage.txt 显示 README.txt 是一个已暂存的文件

# 5. 修改 README.txt 文件并执行命令 git status > Modified.txt
echo "Adding more content to README.txt." >> README.txt
git status > Modified.txt
# 显示 README.txt 是一个已修改的文件

# 6. 对比 Modified.txt 和第一次执行 add 命令之前的 status
cat Modified.txt
cat Untracked.txt
# Modified.txt 显示 README.txt 是一个已修改的文件,Untracked.txt 显示 README.txt 是一个未被跟踪的文件

status 是否一样,并思考原因。

结果不同。第一次执行git add前,README.txt是一个未被跟踪的文件,而在修改已经提交的 README.txt文件后,Git 已经开始跟踪该文件,只是当前修改尚未被添加到暂存区,与未跟踪状态不同。

Thinking 0.2 Git命令


箭头中的add the file、stage the file和commit分别对应的是Git里的哪些命令呢?

add the file对应的是git add命令,用于将未跟踪文件添加到暂存区(Untracked->Staged)。
stage the file对应的是git add命令,用于将已跟踪但被修改的文件添加到暂存区(Modified->Staged)。
commit对应的是git commit命令,用于将暂存区的文件提交到版本库(Staged->Unmodified)。

Thinking 0.3 Git版本

代码文件print.c被错误删除时,应当使用什么命令将其恢复?

使用git checkout -- print.c命令或者git restore <file>命令撤销对print.c文件的删除操作。

代码文件print.c被错误删除后,执行了git rm print.c命令,此时应当使用什么命令将其恢复?

使用git restore --staged print.c命令恢复print.c文件的未暂存状态,然后使用git restore print.c命令恢复print.c文件的未修改状态。

无关文件hello.txt已经被添加到暂存区时,如何在不删除此文件的前提下将其移出暂存区?

使用git restore --staged hello.txt命令将hello.txt文件从暂存区移出。

Thinking 0.4 Git reset

执行以下命令,并观察变化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
> cd learnGit/
> echo "Testing 1" >> README.txt
> git add README.txt
> echo "Testing 2" >> README.txt
> git commit -m "1"
> git commit -m "2"
> echo "Testing 3" >> README.txt
> git commit -m "3"
> git log
#`git log`命令查看提交历史
#可以看到三次提交的commit id分别为
1: a94cd4d430d401235c92308115dddecacb236f6d
2: 42112c824865729cef8c9a937865ac83cf224749
3: 66a074e2349d149d8137fdc948ee9c62f087588b
> git reset --hard HEAD^
# 回退到上一次提交 输出HEAD 现在位于 42112c8 2
> git log
# 再次查看提交历史,可以看到只有两次提交
> git reset --hard a94cd4d430d401235c92308115dddecacb236f6d
# 回退到第一次提交 输出HEAD 现在位于 a94cd4d 1
> git log
# 再次查看提交历史,可以看到只有一次提交
> git reset --hard 66a074e2349d149d8137fdc948ee9c62f087588b
# 再次回到新版本 输出HEAD 现在位于 66a074e 3
> git log
# 再次查看提交历史,可以看到三次提交

使用git reset HEAD...版本回退,上版本是^,上上版本是^^,以此类推,也可以使用~n表示回退到上n次提交。注意git reset --hard本身是危险的,因为它会重写git的提交历史,覆盖掉之前的写入(Testing 1, Testing 2, Testing 3),如果还未提交,则无法恢复。

Thinking 0.5 关于重定向

执行以下命令,并查看结果

1
2
3
4
5
6
7
8
> echo first
# 在终端输出 first
> echo second > output.txt
# 将second写入output.txt,覆盖原有内容
> echo third > output.txt
# 将third写入output.txt,覆盖原有second
> echo forth >> output.txt
# 将forth追加到output.txt,不覆盖原有内容

通过上面的命令,可以非常直观地观察到,>是覆盖写入,>>是追加写入。

Thinking 0.6 关于echo

创建下图内容的文件,命名为test,将创建该文件的命令序列保存在command文件中,并将test文件作为批处理文件运行,将运行结果输出至result文件中。给出command文件和result文件的内容,并对最后的结果进行解释说明(可以从test文件的内容入手). 具体实现的过程中思考下列问题: echo echo Shell Start 与 echo echo Shell Start 效果是否有区别; echo echo $c>file1与echo echo $c>file1 效果是否有区别.

echo
1
2
3
4
5
6
7
#in file command
> touch test
# edit test
> echo "echo Shell Start..." > test
> echo "echo set a = 1" >> test
...
> echo "cat file4>>result"

运行test脚本,结果

1
2
3
4
# in file result
3
2
1

结果解释:

在test文件中,echo命令会将后面的内容输出到终端,因此会逐行输出echo后的内容,脚本的功能是将a赋值为1,b赋值为2,c赋值为a+b,在将c,b,a依次存储到file1,file2,file3中,最后将file1,file2,file3的内容依次追加输入到file4中,再追加到result文件中,因此result文件中的内容为3,2,1。

关于echo echo Shell Start 与 echo echo Shell Start 效果是否有区别; echo echo $c>file1echo 'echo $c>file1' 效果是否有区别

由于带上单引号后会直接输出字符串,echo echo Shell Startecho 'echo Shell Start'最终都将输出Shell Start,效果无区别。对于echo echo $c>file1echo 'echo $c>file1',由于echo echo $c>file1将输出echo $c>file1,其中$c=3,因此file中为3,而echo 'echo $c>file1'将直接输出字符串echo $c>file1到终端,而$c作为参数为空,是因此file中为空,但echo自带换行符,因此file中为空行。

Part2. 难点分析

difficulty

Exercise 0.1

  • 判断回文数,主要考察在CLI中编辑以及其它基本的操作指令,程序本身问题不大。
  • 考察了刚刚学习的make命令和MakeFile的编写,生成可执行文件也是基本的gcc命令。
  • 考察编写shell脚本,需要掌握sed命令和shell脚本中参数的使用,提取需要使用重定向,最后实现sed -n 'kp' $1 >> $2,需要注意sed命令中的参数。
  • 复制到指定文件夹需要使用cp命令,难度不大。

Exercise 0.2

  • 写一个简单的shell脚本,实现批处理,需要掌握循环的写法,循环变量自加的写法比较有意思(i=$(i+1)/let i=i+1)。

Exercise 0.3

  • 题目是多种指令的结合使用,还考察了管道指令。查找可以用grep -n实现,将行号与内容分离需要掌握awk指令,其中参数-F分隔符{print $1}需要掌握含义。管道指令与重定向可以实现执行多步操作并将结果输出到文件中。

Exercise 0.4

  • 字符串替换可以很容易想到使用sed "s/old/new/g" "$inputfile",注意参数为双引号,否则单引号会保留字符串而非实际含义,需要加上g全局替换,以及加上-i参数,否则不会直接修改文件,而是输出到终端。
  • MakeFile的编写有更高要求,需要注意头文件需要自己链接,以及编译得到可执行文件的路径。

Part3. 实验体会

lab0的主要题目要求都是基于OSpre的部分,需要我们学习使用命令行操作,这对很多同学来说是初次实践,但一旦掌握了pre和指导书中对于Git,Shell,gcc,MakeFile的介绍,以及勤搜索、多实践,完成难度不会太大,而实现之后也会发现,命令行操作拥有许多便利之处,在此不再一一列举。
对我而言,通过此次lab0的课下实践,我对于make、sed、awk、shell脚本的掌握有了一定的提升。

Part4. 原创说明

阅读了hugo学长的难点分析,对于从GUI到CLI的转变有了更深理解。