Musel's blog

BUAA-OS-Lab0

字数统计: 2.8k阅读时长: 11 min
2022/03/15

操作系统 Lab0:git与shell

一、实验思考题

thinking 0.1

  • 不一样,第一次add前时README.md属于尚未跟踪文件;第二次修改后的文件属于工作区未暂存以备提交的变更。
  • 不同的原因:未跟踪文件不存在于.git对象库中,而修改后未提交的文件存在一份修改前的文件在.git的对象库。

thinking 0.2

1.add the file :
$ git add $ git commit
2.stage the file :
$ git add
3.commit :
$ git commit

thinking 0.3

1.恢复工作区的printf.c :
$ git checkout -- printf.c
2.$ git rm --cached printf.c后,恢复暂存区文件:

$ git reset HEAD printf.c 
$ git checkout -- printf.c

3.删除暂存区文件,同时保留本地:
git rm --cached Tucao.txt

thinking 0.4

命令与结果

  • 找到提交说明为1的哈希值,使用 git reset –hard ,再使用git log,2和3的版本库消失了。
  • 找到记录下的提交说明为3的哈希值,git reset –hard <Hash-code> ,再使用git log,123版本库均存在,但恢复的2和3的内容均回退为1的内容。

    思考

    git reset –hard <Hash-code>的版本回退问题:
  • HEAD类似指针,各提交版本类似链表。
  • git reset回退到某个版本,只回退了commit信息,不会更改对象库内存储的文件对象.
  • git reset --hard无法恢复,指在本地的源码变为回退版本库的内容,撤销的commit的更改被抹除。
  • 实际上后退的版本库的文件对象仍存在于对象库中,--hard无法恢复指的是文件内容被改写,即被回退到的版本库的文件内容覆盖。

thinking 0.5

1.1克隆时所有分支均被克隆。(正确)

  • 首先,git clone时若未使用git clone -b说明HEAD指向的分支,默认HEAD为master
  • 第一次git clone时,HEAD指向master,此时git clone共12个文件
  • 其后未对master进行修改,只对test1 test2分支进行修改
  • 再次git clone -b master时,git clone共16个文件,说明克隆时所有分支均被克隆

    1.2只有HEAD指向的分支被检出。(正确)

  • git clone -b master,git branch后只有master分支
  • git clone -b test1,git branch后只有test1分支

    2.克隆出的工作区中执行 git log、git status、git checkout、git commit等操作不会去访问远程版本库。(正确)

  • 这四项命令均针对于clone时的版本快照,不会与远程库同步
  • 只有git pull后才会实现本地依照更新的远程库进行更新的步骤
  • 具体实现为:git clone后,在另外的本地库进行对远程库的修改,再回到刚刚git clone的本地库中执行git log等命令时,不会同步远程库的更新

3.克隆时只有远程版本库HEAD指向的分支被克隆。(错误,见1.1)

4.克隆后工作区的默认分支处于master分支。(见1.2)

  • 若使用git clone,工作区默认分支处于master分支
  • 若使用git clone -b branch,工作区默认分支处于branch分支

thinking 0.6

  • echo third > output.txt > 覆盖
  • echo forth >> output.txt >> 追加

thinking 0.7

command

echo 'echo Shell Start...' > test
echo 'echo set a = 1' >>  test
echo 'a=1' >> test
echo 'echo set b = 2' >>  test
echo 'b=2' >> test
echo 'echo set c = a+b' >>test
echo 'c=$[$a+$b]' >>test
echo 'echo c = $c' >>test
echo 'echo save c to ./file1' >>test
echo 'echo $c>file1' >>test
echo 'echo save b to ./file2' >> test
echo 'echo $b>file2' >> test
echo 'echo save a to ./file3' >> test
echo 'echo $a>file3' >> test
echo 'echo save file1 file2 file3 to file4' >> test
echo 'cat file1>file4' >> test
echo 'cat file2>>file4' >> test
echo 'cat file3>>file4' >> test
echo 'echo save file4 to ./result' >> test
echo 'cat file4>>result' >>test

test

Shell Start...
set a = 1
set b = 2
set c = a+b
c = 3
save c to ./file1
save b to ./file2
save a to ./file3
save file1 file2 file3 to file4
save file4 to ./result

result

3
2
1

结果解释

  • save可以将变量和文件的内容重定向至文件

问题1

echo echo Shell Start
echo 'echo Shell Start'
# 显示echo Shell Start
echo `echo Shell Start`
# 显示``反引号内命令的执行结果Shell Start

问题2

  • echo命令无引号时,识别首尾的”echo …无变量无转义字符串… > file”模式,重定向原字符串到文件,且无转移无变量;终端无输出
  • echo命令有单引号时,会把单引号的内容以无转义无变量的形式输出
  • echo命令有反引号时,会把反引号的内容作为命令执行,把命令的输出结果使用echo输出

    testbash.sh

    ```shell
    echo Shell Start…
    echo set a = 1
    a=1
    echo set b = 2
    b=2
    echo set c = a+b
    c=$[$a+$b]
    echo c = $c
    rm file1
    echo echo $c>file1
    echo ‘echo $c>>file1’
    echo echo \$c>>file1

echo echo $c>file1
echo echo $c>file1
echo echo \$c>file1

file1

echo 3

echo $c

echo \3


echo ‘echo $c>>file1’

单引号:除了单引号,全部为字面意义

//变量引用、算术运算和子命令,都失效了
//所以如果单引号之中,还要使用单引号,不能使用转义,需要在外层的单引号前面加上一个美元符号($),然后再对里层的单引号转义。
//更合理的方法是改在双引号之中使用单引号。
//echo $’it's’


echo “echo $c>>file1”
echo “echo $c>>file1”
echo “echo \$c>>file1”

终端

echo 3>>file1

echo $c>>file1

echo \3>>file1

//三个特殊字符除外:美元符号($)、反引号(`)和反斜杠(\)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。
//美元符号用来引用变量,反引号则是执行子命令。
//换行符在双引号之中,会失去特殊含义,Bash 不再将其解释为命令的结束,只是作为普通的换行符。所以可以利用双引号,在命令行输入多行文本。
//双引号的另一个常见的使用场合是,文件名包含空格。这时就必须使用双引号,将文件名放在里面


musel@musel-virtual-machine:~$ echo it’s

s’
its
s


#### file1
> echo $c 

echo echo \$c>file1 的输出  
> 3 

echo \`echo \$c>>file1` 的输出

#### out
> Shell Start...
> set a = 1
> set b = 2
> set c = a+b
> c = 3
> **echo \$c>>file1**   
> \# echo 'echo \$c>>file1' 的输出
>   
> \# echo \`echo \$c>>file1` 输出一个回车

# 二、实验难点
## 1.sed命令的-n 和 -i模式 ——显示与修改的区别
### 不使用 -i 参数时,'d''s'相关的删除、替换等工作都是对于终端显示或重定向的,不修改源文件
- `sed '3p' txt` 首先,sed的命令是按行遍历的,则此条命令在遍历输出txt时,会额外在遍历到第三行时输出第三行
- `sed -n '3p' txt` 在遍历到第三行时输出第三行,输出仅一行
- `sed '3d' txt` 输出源文件,不输出第三行
- `sed -n '3d' txt` -n此时只输出操作行,操作行又被删去,所以无输出
### 使用 -i 参数,对源文件修改
- `sed -i 's/str1/str2/g' txt` 修改,无显示
- `sed -n 's/str1/str2/g' txt` 无显示
- `sed 's/str1/str2/g' txt` 显示替换后的文件
- `sed '/str/d' txt` 不显示包含str的行
- `sed -n '/str/p' txt` 显示包含str的行
- `sed -n '/aaa/p' txt | sed 's/aaa/bbb/g'` 显示替换后的行

## 2.gcc链接库文件 两种命令的区别
- `-include filename`功能相当于在代码中使用`#include<filename>`,代码中不能出现`#include<filename>`
- 对于代码中出现`#include<filename>`的情况,需要使用`-Ipath`链接库

## 3.单引号与双引号的区别
- 单引号无法引用变量,仅作为字符串解析
- 双引号可以引用变量
- `sed -i 's/str1/str2/g' txt`,如果str1的位置是`$1`**参数传递**,需要改成**双引号**

## 4.makefile用法
- 只使用外部Makefile
```makefile
fibo: code/main.c code/fibo.c # 依赖文件
        gcc -c code/main.c code/fibo.c -I./include # 仅列出头文件所在目录即可
        mv fibo.o ./code/fibo.o # -c只编译不链接
        mv main.o ./code/main.o # 在当前makefile文件目录下生成
        gcc -o fibo code/main.o code/fibo.o -I./include
clean: 
        rm ./code/fibo.o
        rm ./code/main.o
        
  • 外层调用内层Makefile
    外层:
    new:./code/main.c ./code/main.c 
          cd ./code && make # 同时执行两条命令
    clean: 
          cd ./code && make clean
    
    内层:
    new:main.c fibo.c
          gcc -c main.c fibo.c -I../include
          gcc main.o fibo.o -o ../fibo
    clean:
          rm main.o
          rm fibo.o
    

三、体会与感想

  1. linux指令以及众多工具的命令过于简洁与灵活,部分资料仅有各种参数的说明而没有使用实例的情况下,较难理解掌握,链接资料读起来也难度不一,经常出现一行代码修改多次仍达不到想要的效果,或对于使用什么样的指令和参数无从下手。
  2. 在虚拟机和git的环境下多尝试使用命令行实践,而不是字面意义上试图看懂各种复杂命令与参数,是上手更快的一种方式。
  3. thinking的引导是很有启发的,在使用实例的复现和探索中,对于git和命令行的掌握更加深入。

四、指导书反馈

  • 关于指导书’课程>初识操作系统>Git 专栏–轻松维护和提交代码>Git文件状态’中,下图类似输入命令与文件状态的状态机,更为清晰。
  • 原图中出现的’add the file’(实际代表git add & git commit)容易与git add造成理解上的混淆
  • 未跟踪
    • 表示没有跟踪(add)某个文件的变化,使用git add即可跟踪文件
    • 工作区文件,未添加对象,易失
  • 未修改
    • 表示某文件在跟踪后一直没有改动过或者改动已经被提交
    • 工作区与对象库文件一致,且暂存区和版本库的目录树均指向此文件
  • 已修改
    • 表示修改了某个文件,但还没有加入(add)到暂存区中
    • 工作区和对象库不一致,暂存区和版本库的目录树均指向此对象库文件
  • 已暂存
    • 表示把已修改的文件放在下次提交(commit)时要保存的清单中
    • 第一次add时:对象库文件与工作区文件一致,暂存区指向对象库中此文件,版本库目录树无此文件指向
    • 后续add修改版本时:对象库存在工作区修改前后的两版,工作区为新版文件,暂存区指向对象库中的新版文件,版本库目录树指向对象库中旧版文件

      五、残留难点

  1. makefile与gcc结合实现多文件链接编译中,对于makefile可以如何更加灵活地使用非常模糊。
CATALOG
  1. 1. 一、实验思考题
    1. 1.1. thinking 0.1
    2. 1.2. thinking 0.2
    3. 1.3. thinking 0.3
    4. 1.4. thinking 0.4
      1. 1.4.1. 命令与结果
      2. 1.4.2. 思考
    5. 1.5. thinking 0.5
      1. 1.5.1. 1.1克隆时所有分支均被克隆。(正确)
      2. 1.5.2. 1.2只有HEAD指向的分支被检出。(正确)
      3. 1.5.3. 2.克隆出的工作区中执行 git log、git status、git checkout、git commit等操作不会去访问远程版本库。(正确)
      4. 1.5.4. 3.克隆时只有远程版本库HEAD指向的分支被克隆。(错误,见1.1)
      5. 1.5.5. 4.克隆后工作区的默认分支处于master分支。(见1.2)
    6. 1.6. thinking 0.6
    7. 1.7. thinking 0.7
      1. 1.7.1. command
      2. 1.7.2. test
      3. 1.7.3. result
      4. 1.7.4. 结果解释
      5. 1.7.5. 问题1
      6. 1.7.6. 问题2
        1. 1.7.6.1. testbash.sh
  2. 2. file1
  3. 3. echo 3
  4. 4. echo $c
  5. 5. echo \3
  6. 6. 单引号:除了单引号,全部为字面意义
  7. 7. 终端
  8. 8. echo 3>>file1
  9. 9. echo $c>>file1
  10. 10. echo \3>>file1
  11. 11. 三、体会与感想
  12. 12. 四、指导书反馈
  13. 13. 五、残留难点