Shell

Bash Shell 环境变量

变量 说明
* 含有所有命令行参数(以单个文本值的形式)
@ 含有所有命令行参数(以多个文本值的形式)
# 命令行参数数目
? 最近使用的前台进程的退出状态码
- 当前命令行选项标记
$ 当前shell的进程 ID (PID)
! 最近执行的后台进程的 PID
0 命令行中使用的命令名称
_ shell 的绝对路径名
BASH 用来调用 shell 的完整文件名
BASHOPTS 允许冒号分隔列表形式的 Shell 选项
BASHPID 当前 bash shell 的进程 ID
BASH_ALIASED 含有当前所用别名的数组
BASH_ARGC 当前子函数中的参数数量
BASH_ARGV 含有所有指定命令行参数的数组
BASH_CMDS 含有命令的内部散列表的数组
BASH_COMMAND 当前正在被执行的命令名
BASH_ENV 如果设置了的话,每个 bash 脚本都会尝试在运行前执行由该变量定义的起始文件
BASH_EXECUTION_STRING 在 -c 命令行选项中用到的命令
BASH_LINENO 含有脚本中每个命令的行号的数组
BASH_REMATCH 含有与指定的正则表达式匹配的文本元素的数组
BASH_SOURCE 含有 shell 中已声明函数所在源文件名的数组
BASH_SUBSHELL 当前 shell 生成的子 shell 数目
BASH_VERS INFO 含有当前 bash shell 实例的主版本号和次版本号的数组
BASH_VERS ION 当前 bash shell 实例的版本号
BASH_XTRACEFD 当设置一个有效的文件描述符整数时,跟踪输出生成,并与诊断和错误信息分离开文件描述符必须设置 -x 启动
COLUMNS 含有当前 bash shell 实例使用的终端的宽度
COMP_CWORD 含有变量 COMP_WORDS 的索引直,COMP_WORDS 包含当前光标所在的位置
COMP_KEY 调用补全功能的按键
COMP_LINE 当前命令行
COMP_POINT 当前光标位置相对干当前命令起始位置的索引
COMP_TYPE 补全类型所对应的整数值
COMP_WORDBREAKS 在进行单词补全时闬作单词分隔符的一组字符
COMP_WORDS 含有当前命令行上所有单词的数组
COMPREPLY 含有由 shell 函数生成的可能补全码的数组
COPROC 含有若干匿名协程 I/O 的文件描述符的数组
DIRSTACK 含有目录栈当前内容的数组
EMACS 如果设置了该环境变量,则 shell 认为其使用的是 emacs shell 缓冲区,同时禁止行编辑功能
ENV 当 shell 以 POSIX 模式调用时,每个 bash 脚本在运行之前都会执行由该环境变量所定义的起始文件
EUID 当前用户的有效用户 ID(数字形式)
FCEDIT fc 命令使用的默认编辑器
FIGNORE 以冒号分隔的后缀名列表,在文件名补全时会被忽略
FUNCNAME 当前执行的 shell 函数的名称
FUNCNEST 嵌套函数的最髙层级
GLOBIGNORE 以冒号分隔的模式列表,定义了文件名展开时要忽略的文件名集合
GROUPS 含有当前用户属组的数组
histchars 控制历史记录展开的字符(最多可有3个)
HISTCMD 当前命令在历史记录中的编号
HISTCONTROL 控制哪些命令留在历史记录列表中
HISTFILE 保存 shell 历史记录列表的文件名(默认是 .bash_history)
HISTFILESIZE 保存在历史文件中的最大行数
HISTIGNORE 以冒号分隔的模式列表,用来决定哪些命令不存进历史文件
HISTSIZE 最多在历史文件中保存多少条命令
HISTIMEFORMAT 设置后,决定历史文件条目的时间戳的格式字符串
HOSTFILE 含有 shell 在补全主机名时读取的文件的名称
HOSTNAME 当前主机的名称
HOSTTYPE 当前运行 bash shell 的机器
IGNOREEOF shell 在退出前必须收到连续的 EOF 字符的数量。如果这个值不存在,默认是 1
INPUTRC readline 初始化文件名(默认是 .inputrc)
LANG shell 的语言环境分类
LC_ALL 定义一个语言环境分类,它会覆盖 LANG 变量
LC_COLLATE 设置对字符串值排序时用的对照表顺序
LC_CTYPE 决定在进行文件名扩展和模式匹配时,如何解释其中的字符
LC_MESSAGES 决定解释前置美元符($)的双引号字符串的语言环境设置
LC_NUMERIC 决定格式化数字时的所使用的语言环境设置
LINENO 脚本中当前执行代码的行号
LINES 定义了终端上可见的行数
MACHTYPE 用“cpu-公司-系统”格式定义的系统类型
MAILCHECK Shell 多久查看一次新邮件(以秒为单位,默认值是 60)
MAPFILE 含有 mapfile 命令所读入文本的数组,当没有给出变量名的时候,使用该环境变量
OLDPWD shell 之前的工作目录
OPTERR 设置为 1 时,bash shell 会显示 getopts 命令产生的错误
OSTYPE 定义了 shell 运行的操作系统
PIPESTATUS 含有前台进程退出状态码的数组
POSIXLY_CORRECT 如果设置了该环境变量,bash 会以 POSIX 模式启动
PPID bash shell 父进程的 PID
PROMPT_COMMAND 如果设置该环境变量,在显示命令行主提示符之前会执行这条命令
PS1 主命令行提示符字符串
PS2 次命令行提示符字符串
PS3 select 命令的提示符
PS4 如果使用了 bash 的 -x 选项,在命令行显示之前显示的提示符
PWD 当前工作目录
RANDOM 返回一个 0~32 767 的随机数,对其赋值可作为随机数生成器的种子
READLINE_LINE 保存了 readline 行缓冲区中的内容
READLINE_POINT 当前 readline 行缓冲区的插入点位置
REPLY read 命令的默认变量
SECONDS 自 shell 启动到现在的秒数,对其赋值将会重置计时器
SHELL shell 的全路径名
SHELLOPTS 已启用 bash shell 选项列表,由冒号分隔
SHLVL 表明 shell 层级,每次启动一个新的 bash shell 时计数加 1
TIMEFORMAT 指定了 shell 显示的时间值的格式
TMOUT select 和 read 命令在没输入的情况下等待多久(以秒为单位)。默认值为零,表示无限长
TMPDIR 如果设置成目录名,shell 会将其作为临时文件目录
UID 当前用户的真实用户 ID (数字形式)

Shell解析器

Linux提供的Shell解析器

cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/usr/bin/bash
/bin/rbash
/usr/bin/rbash
/bin/dash
/usr/bin/dash
/usr/bin/tmux
/usr/bin/screen

默认的解析器

echo $SHELL
/bin/bash

Shell脚本入门

脚本格式

脚本以#!/bin/bash开头(指定解析器)

第一个Shell脚本:helloworld

创建一个Shell脚本,输出helloworld

vim helloworld.sh
#!/bin/bash
echo "helloworld"

脚本的常用执行方式

采用bash或sh+脚本的相对路径或绝对路径

不用赋予脚本+x权限

sh+脚本的相对路径

sh helloworld.sh
helloworld

sh+脚本的绝对路径

sh /home/owenxuan/helloworld.sh
helloworld

bash+脚本的相对路径

bash helloworld.sh
helloworld

bash+脚本的绝对路径

bash /home/owenxuan/helloworld.sh
helloworld

采用输入脚本的绝对路径或相对路径执行脚本

必须具有可执行权限+x

首先要赋予helloworld.sh

sudo chmod 777 helloworld.sh

相对路径执行脚本

./helloworld.sh 
helloworld

绝对路径执行脚本

/home/owenxuan/helloworld.sh 
helloworld
  • 第一种执行方法,本质是bash解析器帮你执行脚本,所以脚本本身不需要执行权限。
  • 第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。

第二个Shell脚本:多命令处理

在/home/owenxuan/目录下创建一个cls.txt,在cls.txt文件中增加“I love cls”

vim batch.sh
#!/bin/bash

cd /home/owenxuan
touch cls.txt
echo "I love cls" >>cls.txt

Shell中的变量

系统变量

echo $HOME
/home/owenxuan

自定义变量

基本语法

  • 定义变量:变量=值
  • 撤销变量:unset 变量
  • 声明静态变量:readonly变量,注意:不能unset

变量定义规则

  • 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
  • 等号两侧不能有空格
  • 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
  • 变量的值如果有空格,需要使用双引号或单引号括起来。

案例实操

定义变量A

A=5
echo $A
5

给变量A重新赋值

A=8
echo $A
8

撤销变量A

unset A
echo $A

声明静态的变量B=2,不能unset

readonly B=2
echo $B
2
B=9
-bash: B: readonly variable

在bash中,变量默认类型都是字符串类型,无法直接进行数值运算

C=1+2
echo $C
1+2

变量的值如果有空格,需要使用双引号或单引号括起来

D=I love you
-bash: world: command not found
D="I love you"
echo $A
I love you

可把变量提升为全局环境变量,可供其他Shell程序使用

export 变量名

vim helloworld.sh
#!/bin/bash

echo "helloworld"
echo $B
sh /helloworld.sh 
Helloworld

发现并没有打印输出变量B的值

export B
sh /helloworld.sh 
helloworld
2

特殊变量

$n

基本语法

n为数字,$0代表该脚本名称,$1-\(9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如\){10}

案例实操

vim parameter.sh
#!/bin/bash
echo "$0  $1   $2"
sh parameter.sh cls  xz
parameter.sh  cls   xz

$#

基本语法

获取所有输入参数个数,常用于循环

案例实操

vim parameter.sh
#!/bin/bash
echo "$0  $1   $2"
echo $#
sh parameter.sh cls  xz
parameter.sh  cls   xz
2

$*

基本语法

这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体

案例实操

vim parameter.sh
#!/bin/bash
echo "$0  $1   $2"
echo $#
echo $*
sh parameter.sh cls  xz 1 2 3
parameter.sh  cls   xz
2
1 2 3

$@

基本语法

这个变量也代表命令行中所有的参数,过$@把每个参数区分对待

案例实操

vim parameter.sh
#!/bin/bash
echo "$0  $1   $2"
echo $#
echo $*
echo $@
sh parameter.sh cls  xz 1 2 3
parameter.sh  cls   xz
2
1 2 3
1 2 3

$?

基本语法

最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了

案例实操

sh parameter.sh cls  xz 1 2 3
parameter.sh  cls   xz
2
1 2 3
1 2 3
echo $?
0

运算符

基本语法

  • “\(((运算式))”或“\)[运算式]”
  • expr + , - , *, /, % 加,减,乘,除,取余

案例实操

计算3+2的值

expr 2 + 3
5

计算3-2的值

expr 3 - 2
1

计算(2+3)X4的值

expr一步完成计算

expr `expr 2 + 3` \* 4
20

采用$[运算式]方式

S=$[(2+3)*4]
echo $S
20

条件判断

基本语法

[ condition ](注意condition前后要有空格)

注意:条件非空即为true,[ atguigu ]返回true,[] 返回false。

常用判断条件

两个整数之间比较

  • = 字符串比较
  • -lt 小于(less than)
  • -le 小于等于(less equal)
  • -eq 等于(equal)
  • -gt 大于(greater than)
  • -ge 大于等于(greater equal)
  • -ne 不等于(Not equal)

按照文件权限进行判断

  • -r 有读的权限(read)
  • -w 有写的权限(write)
  • -x 有执行的权限(execute)

按照文件类型进行判断

  • -f 文件存在并且是一个常规的文件(file)
  • -e 文件存在(existence)
  • -d 文件存在并是一个目录(directory)

案例实操

23是否大于等于22

[ 23 -ge 22 ]
echo $?
0

helloworld.sh是否具有写权限

[ -w helloworld.sh ]
echo $?
0

/home/owenxuan/cls.txt目录中的文件是否存在

[ -e /home/atguigu/cls.txt ]
echo $?
0

多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)

[ condition ] && echo OK || echo notok
OK
[ condition ] && [ ] || echo notok
notok

流程控制

if 判断

基本语法

if [ 条件判断式 ];then 
  程序 
fi 
或者 
if [ 条件判断式 ] 
  then 
    程序 
fi

注意:

  • [ 条件判断式 ],中括号和条件判断式之间必须有空格
  • if后要有空格

案例实操

输入一个数字,如果是1,则输出banzhang zhen shuai,如果是2,则输出cls zhen mei,如果是其它,什么也不输出

vim if.sh
#!/bin/bash

if test $1 -eq "1" 
then
	echo "banzhang zhen shuai"
elif [ $1 -eq "2" ]
then
	echo "cls zhen mei"
fi
bash if.sh 1
banzhang zhen shuai

case 语句

基本语法

case $变量名 in 
  "值1") 
    如果变量的值等于值1,则执行程序1 
    ;; 
  "值2") 
    如果变量的值等于值2,则执行程序2 
    ;; 
  …省略其他分支… 
  *) 
    如果变量的值都不是以上的值,则执行此程序 
    ;; 
esac

注意:

  • case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
  • 双分号“;;”表示命令序列结束,相当于java中的break。
  • 最后的“*)”表示默认模式,相当于java中的default。

案例实操

输入一个数字,如果是1,则输出banzhang,如果是2,则输出cls,如果是其它,输出renyao

vim case.sh
#!/bin/bash

case $1 in
"1")
	echo "banzhang"
;;

"2")
	echo "cls"
;;
*)
	echo "renyao"
;;
esac
bash case.sh 1
1

for 循环

基本语法 1

for (( 初始值;循环控制条件;变量变化 )) 
  do 
    程序 
  done

案例实操 1

从1加到100

vim for1.sh
#!/bin/bash
s=0
for((i=0;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
bash for1.sh 
5050

基本语法 2

for 变量 in 值1 值2 值3… 
  do 
    程序 
  done

案例实操 2

打印所有输入参数

vim for2.sh
#!/bin/bash
#打印数字

for i in $*
do
	echo "ban zhang love $i "
done
bash for2.sh cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd

比较\(*和\)@区别

\(*和\)@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1 \(2 …\)n的形式输出所有参数

vim for.sh
#!/bin/bash

for i in $*
do
	echo "ban zhang love $i "
done

for j in $@
do
	echo "ban zhang love $j"
done
bash for.sh cls xz bd
ban zhang love cls 
ban zhang love xz 
ban zhang love bd 
ban zhang love cls
ban zhang love xz
ban zhang love bd

当它们被双引号“”包含时,“$*”会将所有的参数作为一个整体,以“$1 \(2 …\)n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “\(2”…”\)n”的形式输出所有参数

vim for.sh
#!/bin/bash

for i in "$*"
do
	echo "ban zhang love $i"
done

for j in "$@"
do
	echo "ban zhang love $j"
done
bash for.sh cls xz bd
ban zhang love cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd

while 循环

基本语法

while [ 条件判断式 ] 
  do 
    程序
  done

案例实操

从1加到100

vim while.sh
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
	s=$[$s+$i]
	i=$[$i+1]
done
echo $s
bash while.sh 
5050

read读取控制台输入

基本语法

read(选项)(参数)
	选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
	变量:指定读取值的变量名

案例实操

vim read.sh
#!/bin/bash

read -t 7 -p "Enter your name in 7 seconds " NAME
echo $NAME
bash read.sh 
Enter your name in 7 seconds owen
owen

函数

系统函数

basename基本语法

basename [string / pathname] [suffix]

功能描述:

basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来

选项:

suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。

案例实操

截取该/home/owenxuan/banzhang.txt路径的文件名称

basename /home/owenxuan/banzhang.txt 
banzhang.txt
basename /home/owenxuan/banzhang.txt .txt
owenxuan

dirname基本语法

dirname 文件绝对路径

功能描述:

从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)

案例实操

获取banzhang.txt文件的路径

dirname /home/owenxuan/banzhang.txt 
/home/owenxuan

自定义函数

基本语法

[ function ] funname[()]
{
	Action;
	[return int;]
}
funname

经验技巧

  • 必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
  • 函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)

案例实操

计算两个输入参数的和

vim fun.sh
#!/bin/bash
function sum()
{
    s=0
    s=$[ $1 + $2 ]
    echo "$s"
}

read -p "Please input the number1: " n1;
read -p "Please input the number2: " n2;
sum $n1 $n2;
bash fun.sh
Please input the number1: 2
Please input the number2: 5
7

Shell工具

cut

cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出

基本用法

cut [选项参数]  filename

说明:

默认分隔符是制表符

选项参数说明

选项参数 功能
-f 列号,提取第几列
-d 分隔符,按照指定分隔符分割列

案例实操

数据准备

vim cut.txt
dong shen
guan zhen
wo  wo
lai  lai
le  le

切割cut.txt第一列

cut -d " " -f 1 cut.txt 
dong
guan
wo
lai
le

切割cut.txt第二、三列

cut -d " " -f 2,3 cut.txt 
shen
zhen
 wo
 lai
 le

在cut.txt文件中切割出guan

cat cut.txt | grep "guan" | cut -d " " -f 1
guan

选取系统PATH变量值,第2个“:”开始后的所有路径:

echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/owenxuan/bin
echo $PATH | cut -d: -f 2-
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/owenxuan/bin

切割ifconfig 后打印的IP地址

ifconfig eth0 | grep "inet addr" | cut -d: -f 2 | cut -d" " -f1
10.10.10.30

sed

sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。

基本用法

sed [选项参数]  ‘command’  filename

选项参数说明

选项参数 功能
-e 直接在指令列模式上进行sed的动作编辑。

命令功能描述

命令 功能描述
a 新增,a的后面可以接字串,在下一行出现
d 删除
s 查找并替换

案例实操

数据准备

vim sed.txt
dong shen
guan zhen
wo  wo
lai  lai

le  le

将“mei nv”这个单词插入到sed.txt第二行下,打印

sed '2a mei nv' sed.txt 
dong shen
guan zhen
mei nv
wo  wo
lai  lai

le  le
cat sed.txt 
dong shen
guan zhen
wo  wo
lai  lai

le  le

注意:文件并没有改变

删除sed.txt文件所有包含wo的行

sed '/wo/d' sed.txt
dong shen
guan zhen
ni  ni
lai  lai

le  le

注意:‘g’表示global,全部替换

将sed.txt文件中的第二行删除并将wo替换为ni

sed -e '2d' -e 's/wo/ni/g' sed.txt 
dong shen
ni  ni
lai  lai

le  le

awk

一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。

基本用法

awk [选项参数] ‘pattern1{action1}  pattern2{action2}...’ filename
  • pattern:表示AWK在数据中查找的内容,就是匹配模式
  • action:在找到匹配内容时所执行的一系列命令

选项参数说明

选项参数 功能
-F 指定输入文件折分隔符
-v 赋值一个用户定义变量

案例实操

数据准备

sudo cp /etc/passwd ./

搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。

awk -F: '/^root/{print $7}' passwd 
/bin/bash

搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。

awk -F: '/^root/{print $1","$7}' passwd 
root,/bin/bash

注意:只有匹配了pattern的行才会执行action

只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加"dahaige,/bin/zuishuai"。

awk -F : 'BEGIN{print "user, shell"} {print $1","$7} END{print "dahaige,/bin/zuishuai"}' passwd
user, shell
root,/bin/bash
bin,/sbin/nologin
。。。
atguigu,/bin/bash
dahaige,/bin/zuishuai

注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。

将passwd文件中的用户id增加数值1并输出

awk -v i=1 -F: '{print $3+i}' passwd
1
2
3
4

awk的内置变量

变量 说明
FILENAME 文件名
NR 已读的记录数
NF 浏览记录的域的个数(切割后,列的个数)

案例实操

统计passwd文件名,每行的行号,每行的列数

awk -F: '{print "filename:"  FILENAME ", linenumber:" NR  ",columns:" NF}' passwd 
filename:passwd, linenumber:1,columns:7
filename:passwd, linenumber:2,columns:7
filename:passwd, linenumber:3,columns:7

切割IP

ifconfig eth0 | grep "inet addr" | awk -F: '{print $2}' | awk -F " " '{print $1}' 
10.10.10.30

查询sed.txt中空行所在的行号

awk '/^$/{print NR}' sed.txt 
5

sort

sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。

基本语法

sort(选项)(参数)
选项 说明
-n 依照数值的大小排序
-r 以相反的顺序来排序
-t 设置排序时所用的分隔字符
-k 指定需要排序的列

参数:指定待排序的文件列表

案例实操

数据准备

vim sort.sh 
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6

按照“:”分割后的第三列倒序排序。

sort -t : -nrk 3  sort.sh 
bb:40:5.4
bd:20:4.2
cls:10:3.5
xz:50:2.3
ss:30:1.6
上一篇:Linux awk命令详解


下一篇:Linux 命令终端提示符显示 bash-4.2# 解决方法