6.NULL Video Note

好的工具总是能带来高的效率

VIDEO 1 The Shell

  1. cd -将会在和上一次cd的目录来回切换
  2. rm命令默认非递归的删除,因此删除目录时需要加上-r参数(recursive),才能完整地将目录下的文件删除;而rmdir只能删除空目录
  3. 解释一下常用命令的含义pwd(print work directory), cd(change directory)
  4. -表示当前没有允许的权限。d表示目录,注意目录的x位表示当前能够访问该目录的内容,且需要保证当前目录的父目录都含有x位才能访问。
  5. redirect, < 表示重定向输入, > 表示重定向输出. Some example:
    1
    2
    3
    4
    5
    6
    7
    8
    missing:~$ echo hello > hello.txt
    missing:~$ cat hello.txt
    hello
    missing:~$ cat < hello.txt
    hello
    missing:~$ cat < hello.txt > hello2.txt
    missing:~$ cat hello2.txt
    hello
    >>表示追加(append)
  6. ctrl+L清空终端的命令,返回到顶部。
  7. tail -n将数据中的末尾n行显示出来。
  8. pipe,将两个不相关联的程序连接起来通过input/output连接起来,管道的左边作为一个input, 管道的右边作为一个output。
  9. $表示当前运行在用户模式下; #表示当前运行在系统模式下,可以通过命令sudo su来打开root下的terminal.
  10. xdg-open命令可以打开文件对应的格式
  11. double quotes: backslash, \前面加个!就不会被默认移除
  12. shebang是由脚本开头的字符数字符号和感叹号#!组成的字符序列。当带有shebang的文本文件被用作类Unix操作系统的”可执行文件”时,程序加载器机制将文件初始行的其余部分解析为”解释器指令”。它告诉内核用什么来运行此脚本(比如说python or shell?)

VIDEO 2 Shell Tools and Scripting

  1. different from the single quote(') and double quote("). echo “”中解析出变量放变量(用$符号来表示)。而单引号不会解析变量。
    • $1$9表示argv中第一个到第九个参数
    • $0表示脚本的名字
    • $_(undersocre)表示上一个command的最后一个参数
    • $?(question mark)获取上一个command的error code(一般值为0表示ok, 1表示执行出错)。
    • $#(hash)表示参数的个数
    • $$表示当前进程的ID
    • $@表示所有参数。
  2. !!(bang)代替上一次执行过的command,比如说创建一个目录mkdir ..没有权限,这时候只需要sudo !!, 就会默认表示sudo mkdir ..从而减少了一些重复性的工作。
  3. ;(semicolon)分号可以连接任何命令行。false ; echo "haha"
  4. 脚本中变量用双引号引起来"$1".
  5. 执行脚本source ..
  6. globbing, *(asterisk), {}(curly braces)
  7. tldr(too long, don’t read), 精简版带example的man
  8. test, 查看man手册
  9. 查找文件:
  • find查看man手册
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 查找所有名称为src的文件夹
    find . -name src -type d
    # 查找所有文件夹路径中包含test的python文件
    find . -path '*/test/*.py' -type f
    # 查找前一天修改的所有文件
    find . -mtime -1
    # 查找所有大小在500k至10M的tar.gz文件
    find . -size +500k -size -10M -name '*.tar.gz'
    # 删除全部扩展名为.tmp 的文件
    find . -name '*.tmp' -exec rm {} \;
    # 查找全部的 PNG 文件并将其转换为 JPG
    find . -name '*.png' -exec convert {} {}.jpg \;
  • fd, find的替代物
  • locate, 只能通过文件名,但速度很快。locate(1)当您只是尝试按名称查找特定文件时会更好,该文件您知道存在,但您只是不记得它的确切位置。find(1)当您有一个重点领域需要检查时,或者当您需要其众多优势中的任何一个时,效果会更好
  1. shellcheck检查shell脚本的语法。
  2. 查找代码:
    • grep
    • awk
    • rg(ripgrep)
      1
      2
      3
      4
      5
      6
      7
      8
      # 查找所有使用了 requests 库的文件
      rg -t py 'import requests'
      # 查找所有没有写 shebang 的文件(包含隐藏文件)
      rg -u --files-without-match "^#!"
      # 查找所有的foo字符串,并打印其之后的5行
      rg foo -A 5
      # 打印匹配的统计信息(匹配的行和文件的数量)
      rg --stats PATTERN
  3. 查找shell命令:
  • history
  • Ctrl+R, backward search. 搭配fzf
  1. 文件夹导航:
    • tree
    • broot
    • nnn, 需要接下来去学习
  2. shell中使用变量需要加""(double quote), 当变量中含有命令时需要加括号比如"$(pwd)"
  3. 进行比较时需要加[[]]双括号,比如说if [[ n -eq 12 ]]; then, 注意括号左右要有空格否则出错。
  4. globbing

Exercise2

  1. ls

    1. 所有文件(包括隐藏文件ls -a
    2. 文件打印以人类可以理解的格式输出 (例如,使用454M 而不是 454279954) ls -hl
    3. 文件以最近访问顺序排序ls -clt
    4. 以彩色文本显示输出结果ls --color=always
  2. 设计一个自动化shell。marco函数保存当前工作目录pwd到home目录的一个log文件中,polo函数通过打开log文件中的路径cd跳到之前所保存的目录中。

    方法一:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #! /usr/bin/env bash

    marco() {
    echo "$(pwd)" > "$HOME/marco_history.log"
    echo "save pwd $(pwd)"
    }

    polo() {
    cd "$(cat $HOME/marco_history.log)"
    }

    export可以增加、修改或删除环境变量,仅效力于该次登陆的操作,和第一种方法的时效类似。

    方法二:

    1
    2
    3
    4
    5
    6
    7
    #!/bin/bash
    marco() {
    export MARCO=$(pwd)
    }
    polo() {
    cd "$MARCO"
    }
  3. shell表达式计算的格式为两个(())以及一些逻辑表达式的规范见此处。关于给的test中的语句中>&2以及一些重定向的问题此处给出了答案。>&2表示2是个文件描述符,不是文件名, 因为重定向的对象是文件名; &>则表示同时发送,比如1&>2表示标准输出和标准错误同时输出。

    for循环的格式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #! /bin/bash

    count=1

    chmod u=rwx ./test.sh
    while true
    do
    ./test.sh 2> out.log
    if [[ $? -ne 0 ]]; then
    echo "failed after $count times"
    cat out.log
    break
    fi
    ((count++))
    done

    shellcheck建议增加一行mycmd=$?, 用mycmd来代替$?

  4. 利用xargs命令完成一些操作。xargs命令将标准输入的内容作为参数。此处有关于find后的/的作用,目的是方便为了遇到换行符\n停止解析?? tar命令,压缩文件tar -czvf, 解压文件tar -xzvf, -c表示创建备份文件,-x表示从备份文件中还原文件。-f表示指定备份文件, -v表示显示verbose, -z表示--gzip--ungzip 通过gzip指令处理备份文件。xargs-d参数后面跟字符表示修改xargs的分隔符(默认为空白字符tab、空格、换行符)。

    方法一, xargs -d '\n'指定输入遇到换行符结束:

    1
    find -name '*.html' -type f | xargs -d '\n' tar -cxzf html.zip

    方法二, find -print0打印文件名到标准输出后后面自动跟个null; xargs -0输入遇到null则终止代替空格:

    1
    find -name '*.html' -type f -print0 | xargs -0 tar -cxzf html.zip
  5. 找出当前文件夹下最近使用的文件, 并按照最近使用的时间列出文件

    1
    find type -f | xargs ls -tl | head-1 

VIDEO 3 Editors(Vim)

  1. v进入可视化模式; V进入可视化行模式; ^v(Ctrl + v)进入可视化块模式
  2. Vim大量使用Esc键,因此建议将大小写锁定键设置为Esc键, 可以在ubuntu下使用gnome-tweaks来配置交换修改大小写和Esc, 这里面同样介绍了VScode下的配置
  3. Vim 会维护一系列打开的文件,称为“缓存buffer”。一个 Vim 会话包含一系列标签tab页,每个标签页包含 一系列窗口(分隔面板)。每个窗口显示一个缓存。
  4. :qa全部退出, :wq等价于:x
  5. :tabnew;
  6. :e <文件名>打开要编辑的文件
    • w移动一个单词
    • b回退一个单词
    • e移动到单词末尾, 可以搭配a在光标之后插入文本。
    • ^移动到行首字符
    • $移动到行尾字符
    • 0移动到行首字符前
    • ^U上翻页
    • ^D下翻页
    • gg移动到最后一行
    • 输入number+G则直接跳转到文件中的某一指定行。若不输入number则直接跳到文件第最后一行。
    • H屏幕首行
    • M屏幕中间
    • L屏尾巴行
  7. [f|F|t|T][alpha], find和to功能来找到相应的字母
  8. ^g显示当前编辑文件中当前光标所在行位置以及文件状态信息。
  9. uundo, U撤销在一行中做出的所有改动 ;^r redo
  10. d操作会将删除的内容放入vim中的寄存器中, 以便p操作时粘贴。
    • de删除从光标处到单词尾
    • dw删除一个单词
    • d+上hjkl方向可以删除需要的内容
  11. cchange,功能类似于d,只是操作c会进入insert模式
  12. 在词尾插入e移动到词尾,随后a在当前词尾插入
  13. x删除当前光标所处的字符, 如果在可视模式下就删除选中部分
  14. rreplace, 如ra将当前字符替换为a; R则可以连续替换多个字符。
  15. yyank, ppaste, yw copy one word, 都可以搭配可视化v来使用。
  16. ~改变字母的大小写
  17. [num[h|j|k|l], 如4j向下移动四次
  18. modifier, i指的是inner, a指的是around
    • ci( 改变当前括号内的内容
    • ci[ 改变当前方括号内的内容
    • da' 删除一个单引号字符串,包括周围的单引号
  19. %在配对的括号(parenthese)如:), ], }之间来回切换。在程序调试时用来找不配对的括号是很有用的。
  20. /后紧随一个字符串是在当前所编辑的文档中正向查找改字符串; ?则与/相反,是反向查找。:set ic可以忽略大小写(Ignore Case)会在接下来的查找中持续, :set noic则忽略大小写; :set hls搜索时设置高亮显示, 移除匹配项的高亮显示nohlsearch; :set is(incsearch)查找短语时显示部分匹配, :set noic
  21. 每日一个vim小技巧
  22. 安装并配置插件
  23. Windows下映射CapsLock到ESC需要用到autohotkey脚本工具,添加语句Capslock::Esc即可
  24. ^o回退到光标之前的位置,^i跳转到较新的位置。
  25. s is substitution. The first argument is search string, the second is replacement string.
    • 输入:s/old/new则只将光标所在行的第一个串old修改为new-
    • 输入:s/old/new/g则将全行的匹配串old修改为new
    • :%s/old/new/g则替换整个文件中的每个匹配串。
    • :%s/old/new/gc则会在替换时询问。
    • :#,#s/old/new/g其中#, #代表的是替换操作的若干行中首尾两行的行号
  26. 在vim内执行外部命令的方法,输入:!然后紧接着输入外部的shell命令,如::!ls,回车结束显示。
  27. 可以搭配可视模式将部分内容:w <filename>写到文件名中。
  28. 将磁盘文件内容提取到当前光标行:r <filename>.
  29. :sp分割窗口,^w ^w(double w)在窗口之间来回切换.
  30. F1或者:help打开帮助文档。下面这些参数可以得到该主题的帮助
    • :help w
    • :help c_CTRL-D
    • :help insert-index
    • :help user-manual,阅读Vim的用户手册。
  31. .(period)会完成重复性的工作。
  32. vim命令的补全功能,例如输入:e, 然后按下^D键, Vim会显示以e开始的命令的列表, 接着按下<tab>键会自动自动补全命令。
  33. q: | q?查看vim中的历史命令
  34. 从vim8.0版本开始安装插件只需要将插件git clone~/.vim/pack/vendor/start/文件里就行。

Exercise3

  1. vimtutor

    • 创建文件~/.vimrc能够获得更多的特性。了解更多信息可以输入:help vimrc-intro
    • 文件中注释使用"
    • set nocompatible从默认的Vi兼容模式切换到激活Vim的功能。如果vimrc文件存在它就会默认设置nocompatible, 包含这一条语句是为了以防以一些别的方式加载配置文件。
    • syntax on打开语法高亮
    • set shortmess+=I禁止Vim默认的启动信息:intro,也就是解释vim的版本,以及该如何使用。
    • set number在vim中显示行数
    • set relativenumber显示与当前行的行号和与其相对的行号,其实set number也可以不用加了
    • set laststatus=2在vim底部显示当前状态。2表示不管存在几个窗口总是显示状态栏。
    • set backspace=indent,eol,start。设置backspace的属性,感觉好像vim兼容了对默认情况,经过测试这一行语句似乎没有什么实质性的作用。
    • set hidden可以告诉Vim你拥有未显示在屏幕上未保存的工作, 多一条提示信息。
    • set ignorecase不区分大小写
    • set smartcase只能在ignorecase,它会使得区分大小写更智能。
    • incsearch使用/搜索时会实时搜索,而不是等到Enter键按下时才进行搜索。
    • nmap Q <Nop>对按键Q的解绑操作,按键Q会进入Ex mode, <Nop>意为无操作, 且nmapnnoremap是等价的。nmap是在Normal模式下使用,详情可见:h map-modes
    • set noerrorbells visualbell t_vb=, disable Vim的bell beeping。
    • set mouse+=a鼠标支持, 方便进入可视化选择。a表示all previous modes。应用在vim中的所有五个模式。
    • nmap <Left> :echoe "Use h"<CR>来使用户养成在Normal模式下使用h来左移的习惯。
    • imap <Left> <ESC>:echoe "Use h"<CR>来使用户养成在Insert模式下使用h来左移的习惯,若在Insert模式下使用方向键Left,则回到Normal模式并提示信息”Use h”。因为Vim中的命令行换行是以CR来结尾的(也就是敲完命令需要敲回车换行)才能执行该echo命令回显信息, echoe回显的是错误信息,会加上红色高亮。
  2. 如果创建多级目录的路径不存在则自动创建mkdir -p使用参数p。安装和配置插件内含帮助文档 ctrlp.vim

    • ^P打开模糊搜索
    • c-d切换搜索路径和文件的模式
    • c-t打开该文件作为新的tab; c-v打开该文件分割列; c-x打开该文件分割行; 个人认为这些tmux都可以替代。
    • c-nc-p选择next/previous在ctrlp中的搜索记录
    • 在ctrlp中输入:help ctrlp-mappings查看更多映射的帮助
    • 查找到文件后加:25即可跳到该文件的25行
  3. 使用Chrome上的vimium有关Vim的插件。

    • jk上下移动网页, du以翻页的形式上下移动网页, hl左右移动网页
    • 同样可以像vim一样前缀加上数字,比如4j等。也可以gg跳至网页头和G跳至网页尾
    • f通过标签打开当前网页超链接到当前的tab上,F则打开到新的tab上。
    • 当前tab历史的前进L和回退H
    • 在打开的网页tab之间切换,上一个J, 下一个K
    • 关闭当前标签页x, X恢复关闭的tab
    • 在历史标签中搜索oESC退出
    • 若标签页太多,可以使用T在已有的标签之中搜索,ESC退出
    • ?打开Vimium的帮助文档。
    • r(Reload)刷新当前网页
    • yy将当前的URL复制到剪切板,p将剪切板上的URL在当前tab中打开,P则在新的tab中打开
    • gi将光标焦距到当前网页的第一个输入栏(即搜索栏)
    • b搜索书签打开到当前tab,B打开到新的tab中
    • /在当前网页中使用匹配, 搭配nN
    • t创建新的tab
    • alt+p,pin和unpin当前tab
    • alt+m, 静音和解除静音当前tab
  4. (待做)XMLJSON
    , :wq等价于:x

    VIDEO 4 Data Wangling (TODO)

  5. 正则表达式通常以/开始和结束。正则表达式在线调试工具regex debugger

    • .除换行符之外的”任意单个字符”
    • *匹配前面字符零次或多次
    • +匹配前面字符一次或多次
    • [abc]匹配a,bc中任意一个, 在括号中使用^即为非
    • (RX1|RX2)任何能够匹配RX1RX2的结果
    • ^行首
    • $行尾
  6. sed命令

    • -E参数支持对正则表达式的拓展
  7. uniq命令去除重复行

    • -c参数输出过滤后的行数
  8. sort命令按照数字顺序对输入进行排序(默认情况下是按照字序列排序)

    • -r参数进行倒序排序
    • -n参数表示仅排序到第n个部分
  9. awk编辑器, awk其实是一种编程语言具体可以查看man awktldr awk

  10. 学习一下交互式正则表达式教程

VIDEO 6 Version Control(Git)

  1. Git中的对象可以是blob(数据对象)、Tree或Commit
  2. 所有的snapshot都可以用SHA-1哈希(40位的十六进制字符)来标记,但显然Reference更方便。
  3. HEAD引用可以通过两种方式查看, cat .git/HEAD; git symbolic-ref HEAD
  4. 基础
    • git help <command>:获取git命令的帮助信息
    • git init:创建一个新的git仓库,其数据会存放在一个名为.git的目录下
    • git status:显示当前仓库的状态
    • git add <filename>:添加文件到暂存区(staging Area)
    • git commit:创建一个新的提交; 如何编写良好的提交信息, 为什么要编写良好的提交信息
    • git的提交信息
      1. 用空行将主体与主体分开
      2. 将主题行限制为50个字符
      3. 将主题行大写
      4. 不要以句点结束主题行
      5. 在主题行中使祈使句语句
      6. 将正文包裹在72个字符处
      7. 用正文来解释what why vs. how
    • git log:显示日志历史
    • git log --all --graph --decorate:可视化历史记录(有向无环图)
    • git diff <filename>:显示与暂存区文件的差异
    • git diff <revision> <filename>:显示某个文件两个版本之间的差异
    • git checkout <revision>:更新HEAD和目前的分支
  5. 分支和合并
    • git branch:显示分支
    • git branch <name>:创建分支
    • git checkout -b <name>:创建分支并切换到该分支, 相当于git branch <name>; git checkout <name>
    • git merge <revision>:合并到当前分支
    • git mergetool:使用工具来处理合并冲突
    • git rebase <name>:创建更线性的提交历史
  6. 远端操作
    • git remote:列出远端
    • git remote add <name> <url>:添加一个远端
    • git push <remote> <local branch>:<remote branch>:将对象传送至远端并更新远端引用
    • git branch --set-upstream-to=<remote>/<remote branch>:创建本地和远端分支关联关系
    • git fetch:从远端获取对象
    • git pull:相当于git fetch; git merge
    • git clone <url> <name>:从远端下载仓库并命名为name
  7. 撤销
    • git commit --amend:编辑提交的内容或信息
    • git reset HEAD <file>:恢复暂存的文件
    • `git checkout – :丢弃修改
  8. Git高级操作
    • git config:Git是一个高度可定制的工具
    • git clone --depth=1:浅克隆(shallow clone), 不包括完整的版本历史信息
    • git add -p:交互式暂存
    • git blame:查看最后修改某行的人
    • git stash:暂时移除工作目录下的修改内容
    • git stash pop:恢复工作目录下的修改内容
    • git bisect:通过二分查找搜索历史记录
    • .gitignore:指定故意不追踪的文件