空白无上
Notes Missing-Semester

Missing-Semester

Shell 什么是 Shell Shell 是一种计算机交互接口,可以充分利用计算机的能力 几乎所有的平台都支持某种形式的 Shell,其核心功能都一样:运行你执行程序,输入并获取某个半结构化的输出 使用Shell 打开终端显示如下: 他表示,你现在所在位置是 (表示“home”),前面是主机和用户名(我使用的这个主题

Shell

什么是 Shell

Shell 是一种计算机交互接口,可以充分利用计算机的能力

几乎所有的平台都支持某种形式的 Shell,其核心功能都一样:运行你执行程序,输入并获取某个半结构化的输出

使用Shell

打开终端显示如下:

Feishu image

他表示,你现在所在位置是~(表示“home”),前面是主机和用户名(我使用的这个主题隐藏了)

在提示符中,可以输入命令,命令最终会被 Shell 解析,最简单的命令就是执行一个程序:

➜  ~ date
2024年12月17日 星期二 00时11分20秒 CST
text

上面执行了date这个程序,打印出了当前的日期和时间

我们也可以在执行程序的同时向程序传递参数:

➜  ~ echo hello
hello
➜  ~
text

上面执行了echo程序,并且传递了hello参数

Shell 基于空格分割命令并进行解析,然后执行第一个单词代表的程序,并将后续单词作为程序可以访问的参数

如果想要传递包含空格的参数,要么使用单引号/双引号将其包裹起来,要么使用转义符号\进行转义(My\ Photos)

在程序间创建连接

在 Shell 中,程序有两个主要的“流”:输入流和输出流

程序从输入流中读取信息,并将打印的信息输出到输出流中。通常,输入流就是终端,输出流就是显示器,但是我们可以重定向这些流

最简单的重定向是< file和file >,这两个命令可以将程序的输入输出流分别重定向到文件:

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
text

还可以使用>>来向一个文件追加内容

使用管道(pipes),能更好的利用重定向,|操作符允许我们将一个程序的输出和另一个程序的输入连接起来:

missing:~$ ls -l / | tail -n1
drwxr-xr-x 1 root  root  4096 Jun 20  2019 var
missing:~$ curl --head --silent google.com | grep --ignore-case content-length | cut --delimiter=' ' -f2
219
text

Shell 脚本

注意,脚本并不一定只有用 bash 写才能在终端里调用。比如说,这是一段 Python 脚本,作用是将输入的参数倒序输出

#!/usr/local/bin/python
import sys
for arg in reversed(sys.argv[1:]):
    print(arg)
python

内核知道去用 python 解释器而不是 shell 命令来运行这段脚本,是因为脚本的开头第一行的 shebang

在 shebang 行中使用 env 命令是一种好的实践,它会利用环境变量中的程序来解析该脚本,这样就提高了脚本的可移植性。env 会利用 PATH 环境变量来进行定位

shellcheck

GitHub - koalaman/shellcheck: ShellCheck, a static analysis tool for shell scripts

编写 Shell 脚本有时候会觉得很别扭和反直觉,使用 shellcheck 这样的工具,可以帮忙定位脚本中的错误

tldr

tldr pages

Linux 自带的 man 命令查询手册显示的内容过长,难以快速找到需要的内容,tldr 是一个很好的替代品

fd

GitHub - sharkdp/fd: A simple, fast and user-friendly alternative to ‘find’

fd 是 find 命令的替代品,更简单、更快速、更友好,默认输出着色、默认支持正则表达式、支持 Unicode

如果想要使用索引的方式查找文件,可以使用locate命令

fzf

Configuring shell key bindings

fzf 是一个通用的模糊查找工具,可以对history显示的历史命令进行快速查找

nnn

GitHub - jarun/nnn: n³ The unorthodox terminal file manager

更加完善的文件管理器

编辑器 Vim

Vim 的哲学

在编程的时候,通常人们是在阅读/编辑,而不是在写代码,所以 Vim 是一个多模态的编辑器:它为插入文字和编辑文字有不同的模式

Vim 是可以编程的,可以使用脚本语言(VImScript、Python 等)

编辑模式

Vim 有多种操作模式,他基于你大多数时间都是花在阅读、浏览和进行少量编辑修改的基础上,因此它具有多种模式:

  • 正常模式:在文件中移动光标进行修改

  • 插入模式:插入文本

  • 替换模式:替换文本

  • 可视化模式(一般、行、块):选中文本块

  • 命令模式:用于执行命令

在不同模式下,敲击键盘的含义也不同,比如,插入模式下敲击x会插入字符x,但是在正常模式在会删除当前光标所在的字母,在可视模式下会删除选中文块

默认情况下,Vim 左下角会显示当前的模式,Vim 启动时默认模式是正常模式

可以按下Esc键从任何其他模式返回正常模式。正常模式,按下i键进入插入模式,r键进入替换模式,v键进入可视(一般)模式,V键进入可视(行)模式,Ctrl-v进入可视(块)模式,:进入命令模式

基本操作

插入文本

在正常模式下,键入i键进入插入模式,就可以写入文本了

缓存 标签页 窗口

Vim 会维护一系列打开的文件,称为“缓存”

一个 VIm 回话会包含一系列标签页,每个标签页包含一系列窗口(分隔面板),每个窗口显示一个缓存。跟浏览器不同的是,缓存和窗口不是一一对应的;窗口只是缓存区的视图。一个缓存可以在多个窗口打开,甚至在一个标签页内的多个窗口打开,这样其实很方便,可以查看同一文件的不同部分

命令行

进入命令模式,这个模式有很多功能:打开、保存、关闭文件,以及退出 Vim

  • :q退出(关闭窗口)

  • :w保存(写)

  • :wq保存然后退出

  • e {文件名}打开要编辑的文件

  • ls显示打开的缓存

  • :help {标题}打开帮助文档

  • :help :w打开:w命令的帮助文档

  • :help w打开w移动的帮助文档

Vim的接口其实是一种编程语言

Vim 最重要的设计思想是 Vim 的界面本身是一个程序语言。键入操作(以及他们的助记名) 本身是命令,这些命令可以组合使用。这使得移动和编辑更加高效,特别是一旦形成肌肉记忆

移动

很多时候都是在正常模式下,使用移动命令进行导航

  • 基本移动:hjkl(左、下、上、右)

  • 词:w(下一个词),b(词初),e(词尾)

  • 行:0(行初),^(第一个非空格字符),$(行尾)

  • 屏幕:H(屏幕首行),M(屏幕中间),L(屏幕底部)

  • 翻页:Ctrl+u(上翻),Ctrl+d(下翻)

  • 文件:gg(文件头),G(文件尾)

  • 行数::{行数}<Enter>或者{行数}G

  • 杂项:%(找到配对,比如括号或者注释对)

  • 查找(本行):

  • 向后查找:f{字符}(光标在匹配字符上),t{字符}(光标在匹配字符前)

  • 向前查找:F{字符}(光标在匹配字符上),T{字符}(光标在匹配字符前)

  • ,/;用于导航匹配

  • 搜搜:/{正则表达式},n/N用于导航匹配

选择

进入可视化模式:

  • 可视化:v

  • 可视化行:V

  • 可视化块:Ctrl+v

可以用移动命令来选中

编辑

所有需要鼠标做的事情,现在都可以用键盘来做:采用编辑命令和移动命令来组合完成

这就是 Vim 为什么界面看起来像一个编程语言,VIm 的编辑命令被称为动词,因为动词可以作用于名词

  • i进入插入模式

  • O/o在当前行的上/下面插入行

  • d{移动命令}删除+移动命令

  • 例如,dw删除词,d$删除到行尾,d0删除到行头

  • c{移动命令}改变+移动命令

  • 例如,cw改变词

  • x删除字符(等价于dl)

  • s替换字符(等价于di)

  • 可视化模式+操作

  • 选中文字后,d删除或者c改变

  • u撤销(相当于常用的Ctrl+z),Ctrl+r重做

  • y复制

  • p粘贴

  • ~改变字符的大小

计数

可以用一个计数来结合“名词”和“动词”,这会执行指定操作若干次

  • 3w向后移动三个词

  • 5j向下移动 5 行

  • 7dw删除 7 个词

修饰语

可以用修饰语改变“名词”的意义

修饰语有:i,表示“内部”;a,表示“周围”

  • ci(改变当前括号中的内容

  • ci[改变当前括号中的内容

  • da'删除一个单引号字符串,包括周围的单引号