Shell与命令行基础

最后更新: 2026-01-06 作者: Linux Team
页面目录
目录

Shell概述

什么是Shell?

Shell是Linux系统的命令解释器,它提供了用户与内核交互的界面。用户通过Shell输入命令,内核执行后返回结果。

┌─────────────────────────────────────────────────────────────┐
│                    Shell 工作原理                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   用户 ──→ Shell ──→ 内核 ──→ 硬件                          │
│              ↑         ↓                                    │
│              └──── 响应结果 ────┘                            │
│                                                             │
│   常见Shell类型:                                            │
│   ├── bash   - Bourne Again Shell (最常用)                  │
│   ├── zsh    - Z Shell (功能强大)                           │
│   ├── fish   - Friendly Interactive Shell (易用)           │
│   ├── sh     - Bourne Shell (POSIX标准)                     │
│   └── dash   - Debian Almquist Shell (快速)                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

什么是Bash?

Bash (Bourne Again Shell) 是Linux最常用的Shell,提供了命令补全、历史记录、别名等功能。

# 查看当前使用的Shell
echo $SHELL
# 输出: /bin/bash

# 查看可用的Shell
cat /etc/shells
# 输出:
# /bin/sh
# /bin/bash
# /usr/bin/bash
# /bin/rbash
# /usr/bin/rbash
# /bin/zsh
# /usr/bin/zsh

# 切换Shell
chsh -s /bin/zsh

终端基础

终端快捷键

┌─────────────────────────────────────────────────────────────┐
│                   常用终端快捷键                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   【光标移动】                                              │
│   Ctrl + A / E          移动到行首/行尾                     │
│   Alt  + B / F          按单词移动                         │
│   Ctrl + ← / →          按单词移动(某些终端)              │
│                                                             │
│   【字符编辑】                                              │
│   Ctrl + U              删除光标前内容                     │
│   Ctrl + K              删除光标后内容                     │
│   Ctrl + W              删除光标前单词                      │
│   Alt  + D              删除光标后单词                      │
│   Ctrl + Y              粘贴刚才删除的内容                  │
│   Ctrl + T              交换光标前后字符                     │
│   Alt  + T              交换光标前后单词                     │
│                                                             │
│   【命令执行】                                              │
│   Ctrl + C              终止当前命令                        │
│   Ctrl + Z              挂起当前命令                        │
│   Ctrl + D              退出当前Shell/EOF                   │
│   Ctrl + L              清屏                                │
│   Ctrl + R              反向搜索历史                        │
│   Ctrl + S              暂停输出                            │
│   Ctrl + Q              恢复输出                            │
│                                                             │
│   【Tab补全】                                              │
│   Tab                   自动补全                            │
│   Tab  Tab              显示所有可能选项                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

历史命令

# 查看历史记录
history

# 搜索历史命令
Ctrl + R                          # 反向搜索
(reverse-i-search)`':            # 输入搜索内容

# 执行历史命令
!n                                # 执行第n条命令
!!                                # 执行上一条命令
!-1                               # 执行上一条命令
!string                           # 执行最近以string开头的命令
!?string                          # 执行包含string的命令

# 历史展开
!$                                # 上条命令的最后一个参数
!^                                # 上条命令的第一个参数
!*                                # 上条命令的所有参数
!:n                               # 上条命令的第n个参数
!n:p                              # 显示但不执行第n条命令

# 历史管理
history -c                        # 清空历史
history -d 100                    # 删除第100条
HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "  # 添加时间戳

基础命令

echo - 输出文本

# 基本输出
echo "Hello, Linux!"
echo Hello World

# 转义字符
echo -e "Line1\nLine2"            # 换行
echo -e "Tab\tHere"               # 制表符
echo -e "Color \e[31mRed\e[0m"     # 彩色输出

# 输出到文件
echo "content" > file.txt         # 覆盖
echo "content" >> file.txt        # 追加

# 输出变量
echo $HOME
echo $PATH
echo "User: $USER, Home: $HOME"

# 不输出换行
echo -n "No newline"

printf - 格式化输出

# 格式化输出
printf "%s\n" "Hello"
printf "%d %s\n" 2026 "Linux"
printf "%-10s %-5d\n" Name 25

# 格式化说明符
%s    字符串
%d    整数
%f    浮点数
%x    十六进制
%o    八进制
%05d  补零整数
%8.2f 宽度8位小数2位

date - 日期时间

# 显示日期
date
date "+%Y-%m-%d %H:%M:%S"
date "+%Y%m%d_%H%M%S"

# 格式化选项
%Y    年 (2026)
%m    月 (01-12)
%d    日 (01-31)
%H    时 (00-23)
%M    分 (00-59)
%S    秒 (00-59)
%a    星期缩写 (Mon)
%A    星期全称 (Monday)
%j    年内天数 (001-366)
%U    年内周数

# 设置日期时间(需要root)
sudo date -s "2026-01-06 10:00:00"

# 计算日期
date -d "next Monday"
date -d "yesterday"
date -d "3 days ago"
date -d "+1 week"
date -d "+1 month"
date -d "2026-01-01 + 30 days"

环境变量

# 查看变量
echo $HOME
echo $USER
echo $PATH
echo $PWD
echo $SHELL
echo $LANG
echo $HOSTNAME

# 查看所有环境变量
printenv
env
set

# 设置变量(临时)
export VAR_NAME="value"
VAR_NAME="value"

# 永久设置(用户级)
vim ~/.bashrc
export PATH="$PATH:/new/path"
source ~/.bashrc

# 永久设置(系统级)
sudo vim /etc/environment

文件操作命令

cat - 查看文件

# 基本用法
cat file.txt                      # 显示文件内容
cat file1.txt file2.txt          # 合并显示
cat file1.txt > combined.txt     # 合并写入

# 行号显示
cat -n file.txt                  # 显示行号
cat -b file.txt                  # 非空行编号
cat -s file.txt                  # 多行空行压缩为一行

# 查看不可打印字符
cat -A file.txt                  # 显示Tab($)、行尾(^M$)

# 反向显示
tac file.txt                      # 从最后一行向前显示

less/more - 分页查看

# less - 强大的分页器
less file.txt
less -N file.txt                 # 显示行号
less -S file.txt                 # 行截断
less +/pattern file.txt          # 搜索并跳转到匹配

# less内部命令
/pattern       向下搜索
?pattern       向上搜索
n/N            下一个/上一个匹配
q              退出
g/G           跳转到行
Ctrl+F/B      向下/上滚动一屏
d/u           向下/上滚动半屏

# more - 简单分页
more file.txt
more -10 file.txt                # 每屏10行
more +20 file.txt                # 从第20行开始

head/tail - 文件头尾

# head - 显示文件开头
head file.txt                    # 默认10行
head -n 20 file.txt              # 指定行数
head -c 100 file.txt             # 指定字节数

# tail - 显示文件结尾
tail file.txt                    # 默认10行
tail -n 20 file.txt              # 指定行数
tail -f file.txt                 # 实时追踪文件更新
tail -F file.txt                 # 追踪重命名后的文件
tail -f /var/log/syslog         # 监控系统日志

# 组合使用
head -n 100 file.txt | tail -n 50  # 50-100行
sed -n '50,100p' file.txt           # 50-100行

wc - 统计

# 基本统计
wc file.txt                      # 行数 字数 字节数 文件名
wc -l file.txt                   # 只显示行数
wc -w file.txt                   # 只显示单词数
wc -c file.txt                   # 只显示字节数
wc -m file.txt                   # 只显示字符数

# 统计目录/文件
find . -type f -name "*.txt" | wc -l

管道与重定向

管道 (|)

管道将前一个命令的输出作为后一个命令的输入。

# 语法: command1 | command2 | command3

# 示例
ls -la /etc | grep nginx          # 查找nginx相关
cat /var/log/syslog | grep error  # 查找错误日志
ps aux | grep python              # 查找Python进程
ls -lh | sort -k5 -h              # 按文件大小排序
history | grep apt                # 查找apt历史

重定向

┌─────────────────────────────────────────────────────────────┐
│                    重定向符号                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   >          输出重定向(覆盖)                             │
│   >>         输出重定向(追加)                             │
│   <          输入重定向                                     │
│   << EOF    文本内嵌输入(here document)                   │
│   2>         错误重定向                                     │
│   &>         标准输出和错误重定向                           │
│   2>&1       错误重定向至标准输出                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘
# 输出重定向
echo "Hello" > file.txt           # 覆盖
echo "World" >> file.txt          # 追加

# 输入重定向
wc -l < file.txt                 # 从文件读取输入

# 错误重定向
ls /nonexistent 2> error.txt     # 错误信息写入文件
ls /nonexistent 2>/dev/null      # 丢弃错误信息

# 同时重定向
command > output.txt 2>&1        # 标准输出和错误都保存
command &> all.txt               # 同上(更简洁)

# here document
cat << EOF > file.txt
第一行内容
第二行内容
变量: $HOME
EOF

# here string
cat <<< "string input"

tee - 同时输出到文件和屏幕

# 基本用法
echo "content" | tee file.txt

# 追加模式
echo "more" | tee -a file.txt

# 管道中复制
command1 | tee file.txt | command2

文本处理基础

grep - 文本搜索

# 基本搜索
grep "pattern" file.txt

# 选项
grep -i "pattern" file.txt       # 忽略大小写
grep -r "pattern" directory/      # 递归搜索
grep -n "pattern" file.txt       # 显示行号
grep -c "pattern" file.txt       # 计数
grep -v "pattern" file.txt       # 反向匹配
grep -l "pattern" *.txt          # 只显示文件名
grep -o "pattern" file.txt       # 只显示匹配部分

# 正则表达式
grep "^root" /etc/passwd         # 行首匹配
grep "bash$" /etc/passwd         # 行尾匹配
grep "roo." /etc/passwd           # 任意单字符
grep "ro*" /etc/passwd            # 零或多个o
grep "ro\{2\}" /etc/passwd        # 恰好2个o

# 扩展正则
grep -E "root|admin" file.txt    # 或匹配
grep -E "ro+t" file.txt          # 一个或多个o
grep -E "ro?t" file.txt          # 零或一个o

# 多个模式
grep -e "pattern1" -e "pattern2" file.txt
grep -E "pattern1|pattern2" file.txt
grep "pattern1\|pattern2" file.txt

sed - 文本流编辑器

# 基本语法
sed [options] 'command' file

# 替换
sed 's/old/new/' file.txt         # 替换每行第一个
sed 's/old/new/g' file.txt       # 替换所有
sed 's/old/new/2' file.txt        # 每行第二个
sed 's/old/new/gi' file.txt      # 忽略大小写

# 替换并保存
sed -i 's/old/new/g' file.txt    # 直接修改文件
sed -i.bak 's/old/new/g' file.txt # 备份后修改

# 地址定位
sed '1s/old/new/' file.txt       # 第1行
sed '$s/old/new/' file.txt       # 最后一行
sed '1,5s/old/new/g' file.txt    # 1-5行
sed '/pattern/s/old/new/g' file.txt # 匹配行
sed '5,/pattern/s/old/new/g' file.txt # 5行到匹配行

# 多命令
sed -e 's/old1/new1/' -e 's/old2/new2/' file.txt

# 删除
sed '/pattern/d' file.txt        # 删除匹配行
sed '1,5d' file.txt              # 删除1-5行
sed '/^$/d' file.txt             # 删除空行

# 打印
sed -n '5p' file.txt             # 打印第5行
sed -n '1,10p' file.txt          # 打印1-10行
sed -n '/pattern/p' file.txt    # 打印匹配行

awk - 文本分析工具

# 基本语法
awk 'pattern {action}' file

# 打印列
awk '{print $1}' file.txt        # 打印第1列
awk '{print $1,$3}' file.txt     # 打印1、3列
awk '{print $NF}' file.txt       # 打印最后一列
awk '{print $(NF-1)}' file.txt   # 打印倒数第二列

# 分隔符
awk -F: '{print $1}' /etc/passwd # 以:分隔
awk -F'[, ]' '{print $2}' file   # 多分隔符

# 内置变量
NR    当前记录数(行号)
NF    当前记录字段数
$0    整行内容
$1-$n 各列内容
FS    字段分隔符
OFS   输出字段分隔符

# 条件
awk '/pattern/ {print $1}' file.txt
awk '$3 > 100 {print $0}' file.txt
awk 'NR==5 {print $0}' file.txt
awk 'NR>=5 && NR<=10 {print}' file.txt

# 计算
awk '{sum+=$2} END {print sum}' file.txt
awk '{count++} END {print count}' file.txt

# BEGIN/END
awk 'BEGIN {print "Start"} {print} END {print "End"}' file.txt

cut - 剪切列

# 剪切字符
cut -c 1-10 file.txt             # 1-10字符
cut -c 1,3,5 file.txt            # 1,3,5字符
cut -c -10 file.txt             # 前10字符
cut -c 10- file.txt             # 10字符之后

# 剪切字段
cut -d: -f1 /etc/passwd          # 以:分隔,取第1字段
cut -d' ' -f1-3 file.txt        # 以空格分隔,取1-3字段
cut -d: -f1,3 /etc/passwd        # 取1,3字段

# 配合管道
echo $PATH | tr ':' '\n' | cut -d/ -f3-

其他常用命令

sort - 排序

# 基本排序
sort file.txt                    # 默认按ASCII排序
sort -r file.txt                 # 反向排序
sort -u file.txt                 # 去重排序

# 数值排序
sort -n numbers.txt             # 数值排序
sort -h sizes.txt                # 人类可读数字(1K, 2M)
sort -n -r file.txt             # 降序数值

# 按字段排序
sort -t: -k3 -n /etc/passwd     # 以:分隔,按第3字段排序

# 其他选项
sort -f file.txt                # 忽略大小写
sort -R file.txt                # 随机排序
sort -o output.txt input.txt    # 结果写入文件

uniq - 去重

# 基本用法
uniq file.txt                   # 去重相邻行
sort file.txt | uniq            # 先排序再去重

# 统计
uniq -c file.txt                # 显示重复次数
uniq -d file.txt                # 只显示重复行
uniq -u file.txt                # 只显示不重复行

# 比较字段
uniq -f 1 file.txt              # 跳过前1字段比较
uniq -w 10 file.txt             # 只比较前10字符

tr - 字符转换

# 基本替换
echo "hello" | tr 'a-z' 'A-Z'    # 转大写
echo "HELLO" | tr 'A-Z' 'a-z'    # 转小写

# 删除字符
echo "hello123" | tr -d '0-9'    # 删除数字
echo "hello" | tr -d 'aeiou'     # 删除元音

# 压缩字符
echo "hellooo" | tr -s 'o'       # 压缩重复o
echo "a    b  c" | tr -s ' '     # 压缩空格

# 字符集
tr '[:lower:]' '[:upper:]'
tr '[:digit:]' 'N'

xargs - 参数构建

# 基本用法
echo "file1 file2 file3" | xargs rm

# 逐行处理
cat files.txt | xargs -I {} cp {} /backup/

# 指定分隔符
echo "file1,file2,file3" | xargs -d ',' cp -t /backup/

# 并行执行
echo "1 2 3 4" | xargs -n1 -P4 command

# 组合命令
find . -name "*.log" | xargs rm -f
ls *.txt | xargs -I {} gzip {}

dirname/basename - 路径处理

# 获取目录名
dirname /home/user/docs/file.txt
# 输出: /home/user/docs

# 获取文件名
basename /home/user/docs/file.txt
# 输出: file.txt

# 去除扩展名
basename /home/user/file.txt .txt
# 输出: file

# 组合使用
for f in *.txt; do
    dir=$(dirname "$f")
    base=$(basename "$f")
    echo "Dir: $dir, File: $base"
done

命令组合技巧

&& 和 ||

# && - 前一个成功才执行后一个
cd /tmp && rm *.tmp

# || - 前一个失败才执行后一个
cd /tmp || echo "Cannot cd to /tmp"

# 组合
cd /tmp && rm *.tmp || echo "No .tmp files or error"

命令替换

# $() 方式(推荐)
current_date=$(date +%Y%m%d)
files=$(ls -1)

# `` 方式(兼容老版本)
current_date=`date +%Y%m%d`

# 在命令中使用
cp file.txt "backup_$(date +%Y%m%d).txt"
tar czf "backup_$(hostname)_$(date +%F).tar.gz" /home

算术运算

# expr
result=$(expr 10 + 5)
result=$(expr 10 \* 5)           # 乘法需转义

# $[]
result=$[10 + 5]
result=$[10 * 5]

# let
let "result = 10 + 5"
let "result = $1 * $2"

# bc(浮点数)
echo "scale=2; 10 / 3" | bc
echo "sqrt(100)" | bc -l

命令序列

# 分号分隔,无视成功与否
cd /tmp; ls; cd ~

# 大括号,需在同一行
{ cd /tmp; ls; } > output.txt

# 子Shell
(cd /tmp && rm *.tmp)           # 不影响当前目录

课后练习

实践任务
  1. 练习使用各种终端快捷键(特别是Ctrl+R历史搜索)
  2. 创建一个带时间戳的备份脚本:backup_$(date +%Y%m%d).tar.gz
  3. 使用管道组合命令分析 /var/log/syslog
  4. 练习sed替换、awk统计功能
  5. 用grep配合正则表达式查找passwd文件中的用户信息
  6. 创建一个命令行别名:alias ll='ls -lah'

下一篇预告:我们将学习文本处理三剑客——grep、sed、awk的进阶用法。