5. Bash与系统命令大全

1 常用快捷键

在Bash中,我们可以通过以下快捷键快速移动光标的位置:

  • Ctrl + a:移到行首。
  • Ctrl + b:向行首移动一个字符,与左箭头作用相同。
  • Ctrl + e:移到行尾。
  • Ctrl + f:向行尾移动一个字符,与右箭头作用相同。
  • Alt + f:移动到当前单词的词尾。
  • Alt + b:移动到当前单词的词首。

上面快捷键的 Alt 键,也可以用 ESC 键代替。

使用Ctrl + l快捷键则可以快速清除屏幕,也就是将当前行移到屏幕的第一行,与clear命令作用类似。

而下面的快捷键则可以用于编辑命令行的内容“

  • Ctrl + d:删除光标位置的字符(delete)。
  • Ctrl + w:删除光标前面的单词。
  • Ctrl + t:光标位置的字符与它前面一位的字符交换位置(transpose)。
  • Alt + t:光标位置的词与它前面一位的词交换位置(transpose)。
  • Alt + l:将光标位置至词尾转为小写(lowercase)。
  • Alt + u:将光标位置至词尾转为大写(uppercase)。

使用Ctrl + d的时候,如果当前行没有任何字符,会导致退出当前 Shell,所以要小心。

剪切和粘贴快捷键如下。

  • Ctrl + k:剪切光标位置到行尾的文本。
  • Ctrl + u:剪切光标位置到行首的文本。
  • Alt + d:剪切光标位置到词尾的文本。
  • Alt + Backspace:剪切光标位置到词首的文本。
  • Ctrl + y:在光标位置粘贴文本。

同样地,Alt 键可以用 Esc 键代替。

1.1 自动补全

命令输入到一半的时候,可以按一下 Tab 键,会自动补全命令或路径。

比如,输入cle,再按下 Tab 键,Bash 会自动将这个命令补全为clear

如果符合条件的命令或路径有多个,就需要连续按两次 Tab 键,Bash 会提示所有符合条件的命令或路径。

除了命令或路径,Tab 还可以补全其他值。如果一个值以$开头,则按下 Tab 键会补全变量;

如果以~开头,则补全用户名;

如果以@开头,则补全主机名(hostname),主机名以列在/etc/hosts文件里面的主机为准。

自动补全相关的快捷键如下。

  • Tab:完成自动补全。
  • Alt + ?:列出可能的补全,与连按两次 Tab 键作用相同。
  • Alt + /:尝试文件路径补全。
  • Ctrl + x /:先按Ctrl + x,再按/,等同于Alt + ?,列出可能的文件路径补全。
  • Alt + !:命令补全。
  • Ctrl + x !:先按Ctrl + x,再按!,等同于Alt + !,命令补全。
  • Alt + ~:用户名补全。
  • Ctrl + x ~:先按Ctrl + x,再按~,等同于Alt + ~,用户名补全。
  • Alt + $:变量名补全。
  • Ctrl + x $:先按Ctrl + x,再按$,等同于Alt + $,变量名补全。
  • Alt + @:主机名补全。
  • Ctrl + x @:先按Ctrl + x,再按@,等同于Alt + @,主机名补全。
  • Alt + *:在命令行一次性插入所有可能的补全。
  • Alt + Tab:尝试用.bash_history里面以前执行命令,进行补全。

上面的Alt键也可以用 ESC 键代替。

1.2 其他快捷键

  • Ctrl + j:等同于回车键(LINEFEED)。
  • Ctrl + m:等同于回车键(CARRIAGE RETURN)。
  • Ctrl + o:等同于回车键,并展示操作历史的下一个命令。
  • Ctrl + v:将下一个输入的特殊字符变成字面量,比如回车变成^M
  • Ctrl + [:等同于 ESC。
  • Alt + .:插入上一个命令的最后一个词。
  • Alt + _:等同于Alt + .

上面的Alt + .快捷键,对于很长的文件路径,有时会非常方便。因为 Unix 命令的最后一个参数通常是文件路径。

mkdir foo_bar
cd #按下 Alt + .

上面例子中,在cd命令后按下Alt + .,就会自动插入foo_bar

2 文件管理

linux的基本概念是一切皆文件,所有我们在linux中看到的东西本质上都是某些属性不同的文件。

比如目录,实际上也是一个文件,你完全可以编辑一个目录文件:

image.png

上图中就是用vim直接编辑一个目录看到的数据,可以看到,它本质上就是一个文件,存储了其子目录文件的一些信息。

包括网络套接字、进程、硬盘等等一切,在Windows系统上看上去有些抽象的概念,在linux系统都是文件,我们都能直接编辑它们、或者输出它们获取相关信息。

2.1 文本输出

首先我们来看一些可以直接输出文本文件的命令,它们会把文本内的内容直接打印到命令行,这样我们就不需要用vim等编辑器。

最常用的是cat,它可以将文件的内容显示在标准输出:

cat text1.txt

它也可以同时输出多个文件内容。

cat text1.txt text2.txt

它与重定向结合,就可以合并多个文件。

# 合并文本文件
cat text* > text.all

# 合并二进制文件
cat movie.mpeg.0* > movie.mpeg

如果调用cat命令时没有任何参数,它将读取标准输入,然后显示到标准输出,按下Ctrl + d,将会结束cat读取标准输入。

利用这一点,可以将键盘输入写入指定文件,按下Ctrl + d结束输入:

cat > lazy_dog.txt

它的参数如下。

  • -n 输出结果显示行号
  • -s 将多个连续的空白行,输出为一行
  • -A 输出结果中显示控制符,比如Tab键显示为^I,行尾显示$

cat支持Here document,显示多行文本。

cat << _EOF_
<HTML>
         <HEAD>
                <TITLE>$TITLE</TITLE>
         </HEAD>
         <BODY>
                <H1>$TITLE</H1>
                <P>$TIME_STAMP</P>
         </BODY>
</HTML>
_EOF_

Here document 常在脚本当中作为输入的手段。

sort -k2 <<END
> 1 apple
> 2 pear
> 3 banana
> END

1 apple
3 banana
2 pear

如果使用<<-代替<<,行首的tab键将被剥离。

cat虽然好用,但它会直接输出文本所有内容,在某些时候并不方便,比如一个文本文件里面的内容有几万行,我只希望看它前几行确认是否是我想要的文件、或者只想看最后几行的日志。

只是head命令就派上用场了,它可以返回文本文件的头部,默认显示10行。

-n参数指定显示的行数。

head -n 5 ls-output.txt

tail命令则可以返回文本文件的尾部内容,默认显示10行,-n参数指定显示的行数。

tail -n 5 ls-output.txt

-f会实时追加显示新增的内容,常用于实时监控日志,按Ctrl + c停止。

tail -f /var/log/messages

此外在某些时候,我们还希望能看到文本的行数,就可以使用nl命令,它可以为文本文件添加行号:

nl example.txt

最后,我们还可以用wc命令对一个文本文件进行统计(word count),一共有三个值,分别为行数、词数和字节数。

wc ls-output.txt

 7902 64566 503634 ls-output.txt

如果使用-l参数,则只输出行数。

ls /bin /usr/bin | sort | uniq | wc -l

2728

2.2 文本排序与合并

sort命令可以将文本文件的所有行排序后输出。

sort file1.txt file2.txt file3.txt > final_sorted_list.txt

它的常用参数如下。

  • -b:默认情况下,排序用的是每行的第一个字符。这个参数忽略每行开头的空格,从第一个非空白字符开始排序。
  • -f:让排序不区分大小写。
  • -n: 按照数值排序,而不是字符值,用于行首是数值的情况。
  • -r:按相反顺序排序。结果按照降序排列,而不是升序。
  • -k: 指定按照每行的第几个字段(从1开始)排序,而不是按照行首字符排序。该属性可以多个连用,用于指定多重排序标准,还可以指定每个字段指定排序标准,这些值与全局属性一致,比如b(忽略开头的空格),n(数值排序),r(逆向排序)等等。
  • -m:把每个参数看作是一个预先排好序的文件。把多个文件合并成一个排好序的文件,而没有执行额外的排序。
  • -o :把排好序的输出结果发送到文件,而不是标准输出。
  • -t :定义字段分隔字符。默认情况下,字段由空格或制表符分隔。
  • -u:输出结果中删除重复行
sort --key=1,1 --key=2n distros.txt

上面命令中,第一个--key指定第一排序标准是只用第一字段(1,1),也可以指定使用第一字段第一个字符(1.1);第二排序标准是第二字段,按数值排序。

uniq命令则可以在排序后的行中,删除所有重复的行,保证所有输出没有重复。

ls /bin /usr/bin | sort | uniq

它的参数如下。

  • -c 输出所有的重复行,并且每行开头显示重复的次数。
  • -d 只输出重复行,而不是不重复的文本行。
  • -f n 忽略每行开头的 n 个字段,字段之间由空格分隔,正如 sort 程序中的空格分隔符;然而, 不同于 sort 程序,uniq 没有选项来设置备用的字段分隔符。
  • -i 在比较文本行的时候忽略大小写。
  • -s n 跳过(忽略)每行开头的 n 个字符。
  • -u 只是输出独有的文本行。这是默认的。
  • -V 按照版本号排序。

-V参数可以按版本号排列(从小到大)。

sort -V input.txt


1.0.15
1.3.0
2.1.2
3.0.0

-rV参数可以按版本号逆序排列。

sort -rV input.txt


3.0.0
2.1.2
1.3.0
1.0.15

2.3 文本处理

在特殊情况下,比如排查大量的日志时,我们往往需要定位某些日志数据、而不是去一个一个看所有的日志数据。

此时我们就可以通过下面这些命令对文本数据进行处理。

首先时cut,它可以用来从文本行中抽取文本并输出到标准输出。它能够接受多个文件参数或者标准输入。

它的参数如下。

  • -c char_list 抽取指定范围的文本
  • -f field_list 抽取指定字段,字段之间可以tab分隔也可以逗号分隔
  • -d delim_char 指定字段分隔符,默认是tab键
  • --complement 抽取整个文本行,除了那些由-c 和/或-f 选项指定的文本。
# 抽取每行的第三个字段
cut -f 3 distros.txt

# 抽取每行的第7到第10个字符
cut -c 7-10 distros.txt

# 抽取每行的第23个到结尾的字符1
cut -c 23- distros.txt

# 指定字段分隔符为冒号
cut -d ':' -f 1 /etc/passwd

grep程序则可以用于搜索符合某个模式的行,并把搜索结果输出到标准输出。

grep keyword foo.txt

上面命令输出foo.txt之中匹配keyword的行。

grep程序可以同时搜索多个文件。

grep keyword f*.txt

上面命令输出多个文件中匹配keyword的行。

-l参数输出匹配的文件名,而不是文件行。

grep -l bzip dirlist*.txt

如果想搜索文件名,而不是文件内容,可以使用重定向。

ls /usr/bin | grep zip

上面命令会输出/usr/bin目录中,文件名中包含子字符串zip的所有文件。

参数的含义。

  • -c--count 输出匹配的数量,而不是匹配的文本行。如果使用了-v,则输出不匹配的数量。
  • -h--no-filename 应用于多文件搜索,不在每行匹配的文本前,输出文件名
  • -i--ignore-case 忽略大小写
  • -l--files-with-matches 输出包含匹配项的文件名,而不是文本行本身
  • -L--files-without-match 类似于-l,但输出不包含匹配项的文件名
  • -n--line-number 每个匹配行之前输出其对应的行号
  • -v--invert-match 只返回不符合模式的行

如果你还想要对文本进行更加精细化的处理,那么还可以使用sed命令,它可以对文本进行相当精细的处理,下面是一些例子:

# 输出前5行
sed -n '1,5p' distros.txt

# 输出包含指定内容的行
sed -n '/SUSE/p' distros.txt

# 输出不包含指定内容的行
sed -n '/SUSE/!p' distros.txt

# 替换内容(只替换第一个)
sed 's/regexp/replacement/' distros.txt

# 替换内容(全局替换)
sed 's/regexp/replacement/g' distros.txt