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) # 不影响当前目录
课后练习
实践任务
- 练习使用各种终端快捷键(特别是Ctrl+R历史搜索)
- 创建一个带时间戳的备份脚本:
backup_$(date +%Y%m%d).tar.gz - 使用管道组合命令分析
/var/log/syslog - 练习sed替换、awk统计功能
- 用grep配合正则表达式查找passwd文件中的用户信息
- 创建一个命令行别名:
alias ll='ls -lah'
下一篇预告:我们将学习文本处理三剑客——grep、sed、awk的进阶用法。