Linux笔记-常用命令-Shell与文本处理
本文最后更新于 2025年9月22日 凌晨
“Linux笔记”系列博客是在阅读学习《鸟叔的LINUX私房菜》书籍时形成的思维导图,将其整理为笔记形式。包含以下部分:
Bash shell
type 查询命令是否为shell的内置命令
ulimit 限制用户可用的系统资源
详见私房菜P329
alias 设置命令别名
语法
- 设置别名:alias 别名=’命令’
- 显示所有已设置的别名:alias
- 删除别名:unalias
history 命令历史
语法
- 显示缓存中的历史:history
- 列出最近的n条历史:history n
- 执行第n条历史:!n
- 执行上一条命令:!!
- 由最近历史向前查找以command开头的命令,并执行:!command
source 读取配置文件
语法:
source 配置文件(也可用小数点 . 来代替source,如 . ~/.bashrc,中间有空格)
为所有用户配置bash:在/etc/profile.d/目录下建立*.sh文件,写入要配置的别名、变量、环境变量(要用export转为环境变量)、配置等
为个别用户配置bash:修改~/.bashrc文件
登录时bash配置文件的读取顺序详见私房菜P339
一、变量相关
echo 输出变量
语法:
echo $PATH 或 echo ${PATH}
echo -e 可以使用反斜杠的特殊字符,如\n、\t
变量设置规则
- 设置变量时用等号连接,如:myname=vbird
- 变量名不能以数字开头
- 等号两边不能直接出现空格,如:myname=vbird as是错的
- 变量内容若有空格可用单引号或双引号,双引号中的特殊字符保留原本功能,单引号中的特殊字符仅为一般字符,如var=”lang is $LANG”,$LANG替换为变量内容
- 可用反斜杠\将特殊字符( [Enter]、$、\、空格、’ )转义为一般字符,如:myname=vbird\ tsai
- 若要扩增变量内容,可以如:PATH=”$PATH”:/home/bin 或 PATH=${PATH}:/home/bin
- 若要获得额外的命令所提供的信息时,可用 $(命令) ,如:version=$(uname -r)
- 可使用unset取消变量,如:unset myname
- 变量的数值计算,用$((运算式)),如 total=$(( ${firstnu}*${ secnu} )),但bash中数值计算最多只能到整数
env 显示所有环境变量
bash中一些特殊的变量,详见私房菜P322-324
set 显示所有环境变量与自定义变量
export 自定义变量转成环境变量
语法
export myname
显示所有环境变量:export
子进程仅会继承父进程的环境变量,不会继承父进程的自定义变量
locale 显示当前的语系变量的设置
- locale -a 显示系统支持的所有语系
- 出现乱码问题,通常需要修改语系,只需修改LANG和LC_ALL这两个环境变量,其他语系变量就会被覆盖,例:LANG=en_US.UTF-8 ; export LC_ALL=en_US.UTF-8
- 常用语系:中文:zh_CN.GB2312、zh_CN.UTF-8、英文:en_US.UTF-8
read 读取来自键盘输入的变量
语法:
read [-pt] 变量
选项
- -p:后接提示字符
- -t:后接等待的秒数
declare 声明变量的类型
语法:
declare [-aixr] 变量
选项
- -a:声明为数组类型
- -i:声明为整数类型
- -x:声明为环境变量
- -r:设置为只读类型,不可修改和unset
环境变量转为自定义变量:declare +x 变量
与typeset用法相同
二、 通配符
- *:匹配任意0到无穷多个字符
- ?:匹配1个字符
- [ ]:匹配指定字符范围内的任意个字符,如[abcd]
- [ - ]:匹配在编码顺序内的所有字符,如[0-9]
- [^ ]:表示反向选择,如[^abc]表示非a、b、c的其他字符
三、 特殊符号
通配符与特殊符号也可在shell脚本中使用
- #:注释符号,shell脚本中同
- \:转义符,将通配符或特殊字符转为一般字符
- | :管道符
- ;:连续命令执行符
- &&与 || :具有相关性的命令执行的判断
- ~:用户家目录
- $:变量前导符
- &:任务管理
- !:逻辑运算的非
- / :路径分隔符号
- >与>>与<与<<:数据流重定向
- ‘’ :单引号,其中的特殊字符仅为一般字符,如$PATH不会进行替换
- “”:双引号,其中的特殊字符保留原本功能,如$PATH会进行替换,若单纯要输入$要用转义符
- ( ):子shell的起始与结束
- $():引用额外命令提供的信息进行替换
- { }:用于一串命令执行时,{}中的命令会在当前shell中执行,也可以用于变量变形与替换
四、 数据流重定向
- >:覆盖地重定向标准输出到文件
- >>:累加地重定向标准输出到文件
- 2>:覆盖地重定向标准错误输出到文件
- 2>>:累加地重定向标准错误输出到文件
- <:由键盘输入的数据,改由文件输入
- <<:设置结束的输入字符
- /dev/null:黑洞设备,丢弃任何导向这个设备的数据
- 若要将标准输出与错误输出写到同一个文件,可以用 > list 2>&1
五、 命令执行的判断依据
cmd1 ; cmd2:不考虑相关性,连续地执行命令
cmd1 && cmd2:若cmd1执行完毕且正确,则执行cmd2,反之不执行
依据前一个命令的 $? 变量返回值判定,若$?=0,则执行cmd2,若$?≠0,则不执行。
$?:上一个命令返回值,当命令成功执行时返回0,否则返回非0值。
cmd1 || cmd2:若cmd1执行完毕且错误,则执行cmd2,反之不执行
例:
1 | |
六、管道命令
管道命令用竖线 | 分隔,将前一个命令的stdout作为stdin输入到下一个命令。
支持管道的命令指既可以从文件读取,也可以从标准输入读取:cat、less、more、head、tail、cut、grep、sort、wc、uniq、tee、tr、col、join、paste、expand、split、xargs、sed、awk
cut 以行为单位,切出数据的某一段,用于具有格式的数据,如last的输出
语法
- cut -d ‘分割字符’ -f n [filename]
- cut -c 字符区间 [filename]
选项
- -d:后接分割字符
- -f:用-d的分割字符划分为数段,取第n段
- -c:以字符为单位取出固定区间
例子
- echo ${PATH} | cut -d ‘:’ -f 5
- last | cut -c 1-9
grep 查找匹配的行并打印,支持正则表达式
默认就支持基础正则表达式
语法:
grep [-ABcinv] ‘string’ [filename]
选项
- -An:后接数字,除了找到string的行,后面n行也列出来
- -Bn:后接数字,除了找到string的行,前面n行也列出来
- -c:计算找到字符的行数
- -i:忽略大小写的不同
- -n:输出行号
- -v:反向选择,选取没有“string”的行
- -E:支持拓展正则表达式(等价于egrep)
例子
- last | grep ‘root’ | cut -d ‘ ‘ -f 1
- last | grep -v ‘root’
sort 以行为单位进行排序
语法:
sort [-ntk] [filename]
选项
- -n:以数字进行排序(默认以字符排序)
- -t:后接分隔字符
- -k num:用-t的分割字符划分为数段,用第num段进行排序
例子
- cat /etc/passwd | sort -t ‘:’ -k 3 -n
uniq 对于重复的行,仅保留一行
语法:
uniq [-ic]
选项
- -i:忽略大小写的不同
- -c:进行计数
例子
- last | cut -d ‘ ‘ -f 1 | sort | uniq
- last | cut -d ‘ ‘ -f 1 | sort | uniq -c
wc 计算行数、字符数等
语法:
wc [-lwm] [filename]
选项
- -l:计算行数
- -w:计算单词数
- -m:计算字符数
例子
- last | grep ‘root’ | wc -l
tee 双向重定向,将数据同时分流到文件与屏幕
语法:
tee [-a] file
选项
- -a:以累加的形式写入文件(默认覆盖)
例子
- last | tee last.list | cut -d ‘ ‘ -f 1
用于在管道中保存一份中间数据的缓存
tr 删除或替换字符
语法:
tr [-d] ‘char1’ ‘char2’
选项
- -d:删除char1字符,若无-d选项则将char1替换为char2
例子
- last | tr ‘[a-z]’ ‘[A-Z]’
- cat /etc/passwd | tr -d ‘:’
col 将tab键替换为对等的空格键
语法:
col -x
例子
- cat /etc/man_db.conf | col -x
相同作用expand、unexpand,详见私房菜P357
join 将两个文件中,有相同数据的那一行合并
详见私房菜P356
paste 直接将两个文件的对应两行连接起来,以Tab键隔开
语法:
paste [-d] file1 file2
选项
- -d:后接分隔符,默认为Tab键
例子
- paste /etc/passwd /etc/shadow
- cat /etc/group | paste /etc/passwd /etc/shadow -
split 依据文件大小或行数将大文件划分为小文件
语法:
split [-bl] file 前缀名
选项
- -b:以大小划分,后接文件大小
- -l:以行数划分,后接行数
- 前缀名:小文件的前缀名,以aa、ab、***ac等命名小文件
例子
- 划分为servicesaa、servicesab等的300k的小文件:split -b 300k /etc/services services
- 将小文件合并:cat services* >> servicesback
- 将ls的输出信息每10行记录为一个文件:ls -al /etc | split -l 10 - lsetc
减号放在文件名的位置,可以代表此处文件由stdin输入或由stdout输出,如:
tar -cv -f - /home | tar -xv -f - -C /tmp/homeback
xargs 从stdin解析出参数
用途:
从stdin解析出参数。针对某些不支持管道(不支持stdin输入)的命令,通过xargs从stdin获得参数,从而可以用于管道
语法:
xargs [-0epn] command
选项
- -0:如果输入的stdin含有特殊字符,例如 ` 、\、空格等字符时,这个-0参数可以将它还原成一般字符,这个参数可以用于特殊状态
- -e:这是EOF (end of file) 的意思,后面可以接一个字符,当xargs分析到这个字符时,就会停止工作
- -p:在执行每个命令时,都会询问使用者
- -n:后面接次数,每次command命令执行时,要使用几个参数
例子
- cut -d ‘:’ -f 1 /etc/passwd | head -n 3 | xargs -n 1 id (每次丢一个参数给id命令来执行)
- cut -d ‘:’ -f 1 /etc/passwd | head -n 3 | xargs -e’sync’ -n 1 id
- find /usr/sbin -perm /7000 | xargs ls -l (ls不支持stdin输入,使用xargs后由管道传来的stdin解析出参数,填入ls -l后面)
- find /home -name “*.java” | xargs wc -l (将管道传来的stdout(find找到的文件名列表)解析为参数(一个个文件名)填入wc -l后面,wc去读java文件。wc会被执行很多遍。此条命令的作用是查询/home下每个java文件各自的行数)
- find /home -name “*.java” | wc -l (将管道传来的stdout直接作为标准输入(find找到的文件名列表)输入到wc -l中。wc仅执行一遍。此条命令的作用是查询/home下java文件的数量)
- find /home -name “*.java” | xargs grep ‘123’
文本格式化处理
grep、sed、awk并称Linux三剑客
grep 查找匹配的行并打印,支持正则表达式,支持文件读取和标准输入
用法见上文
sed 文本编辑工具,可进行替换、删除、新增、选定等,支持RE,支持文件读取和标准输入
语法:
sed [-nfri] ‘操作’ [filename]
选项
- -n:使用安静模式,仅显示出被sed处理过的那一行,而非显示文件的所有行
- -f:后接scriptfile,执行scriptfile中的命令
- -r:使用拓展正则表达式
- -i:直接修改原文件内容,而非屏幕输出
‘操作’ 的格式:定位1[,定位2]编辑命令 [内容]
定位方式
- 行号
- /正则表达式/
编辑命令
- a:新增,在指定行的下一行添加
- c:替换,替换n1,n2之间的行
- d:删除,通常后面不接内容
- i:插入,在指定行的上一行添加
- p:打印,通常与sed -n一起使用
- s:查找替换,用法与vim相同, n1,n2s/word1/word2/g 或 s/word1/word2/g
例子
- nl /etc/passwd | sed ‘2a drink’ 在第2行后(即第3行)插入一行drink
- nl /etc/passwd | sed ‘2,5c No 2-5 number’ 替换第2~5行
- nl /etc/passwd | sed ‘2,5d’ 删除第2~5行
- nl /etc/passwd | sed ‘2,$d’ 删除第2到最后一行
- nl /etc/passwd | sed -n ‘5,7p’ 打印第5~7行
- nl /etc/passwd | sed -n ‘/MAN/p’ 打印匹配MAN的行
- nl /etc/passwd | sed -n ‘2,/MAN/p’ 打印从第2行到第一次匹配MAN的行
- nl /etc/passwd | sed ‘s/^#.*$//g’ 把以#开头的行替换为空行
- nl /etc/passwd | sed ‘1,3s/^/#/‘ 在1~3行行首加上#,用于注释某些行
- nl /etc/passwd | sed ‘2a Drink tea or\
- > drink beer?’ 反斜杠加回车可以插入多行数据
awk 将文件的每一行分为数个字段来处理,常用于格式化输出。支持RE,支持文件读取和标准输入
语法:
awk ‘条件{操作} 条件{操作}…’ [filename]
awk每次读入一行,将一行的数据分段放入$1、$2等变量中,根据条件判断是否要执行后面的操作。再读取下一行,重复上面步骤。
每一行的每个字段有其变量名,为$1、$2等。$0代表一整列数据。特殊变量:NF:每一行拥有的字段数,NR:目前处理的是第几行,FS:目前的分割字符,默认是空格。设置分割字符:-F’:’
例子
- last -n 5 | awk ‘{print $1 “\t “ $3}’ 列出第1和3字段,并以Tab分割(注意单引号中出现的非变量的文字部分要用双引号括起来)
- last -n 5 | awk ‘{print $1 “\t lines: “ NR “\t columns: “ NF}’
- last -n 5 | awk ‘BEGIN{FS=”:”} $3<10{print $1 “\t “ $3}’ 以冒号为分隔符,当第三字段大于10时打印第1和3字段
- cat pay.txt | awk ‘NR==1{printf “%10s %10s %10s %10s %10s\n”,$1,$2,$3,$4,”Total”} \
- NR>=2{total=$2+$3+$4; printf “%10s %10d %10d %10d %10.2f\n”,$1,$2,$3,$4,total}’
printf 格式化输出
语法:
printf ‘格式字符串’ 实际内容
printf不能直接读取文件且不支持管道,要用$( )读取文件提供给printf
用法与C语言printf类似,s代表字符串,i代表整数,d代表十进制数,f代表浮点数
例子
- printf ‘%s\t %s\t %s\t %s\t %s\t \n’ $(cat printf.txt)
- printf ‘%10s %5i %5i %5i %8.2f \n’ $(cat printf.txt | grep -v ‘Name’)
- printf ‘\x45\n’ 输出ACSII码值为十六进制的数值0x45(十进制69)的字符
diff 对比纯文本文件
语法:
diff [-bBi] fromfile tofile
选项
- -b:忽略一行中多个空白的区别
- -B:忽略空白行的差别
- -i:忽略大小写的差别
- fromfile:原始文件
- tofile:目标文件
cmp 利用字节单位对比
详见私房菜P382
patch 利用diff生成的补丁文件更新旧文件
详见私房菜P383