变量
一、什么是变量
简单说就是让一个特定的字符串代表不固定的内容
a=1
b=2
a和b都是变量的名字,1和2分别是a和b变量的值>
echo $a //查看变量的值
echo $b
二、变量的设定
设定规则:
1 变量名与变量内容以一个等号 = 的连结,且等号两边不能有空格。如下所示:
wo=xiaohuihui
2 变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误:
2wo=xiaohuihui
bash: 2wo=wocaocian: command not found...:
3 变量内容若有空格符可使用双引号 " 或单引号' 将变量内容组合起来,但双引号内的特殊字符如 ! 等可以保有原本的特性,如下所示:
var="lang is $LANG"
则
echo $var
可得
lang is en_us
感叹号 ! 不可以在shell命令行里直接在双引号里使用,但是可以在脚本中使用。
• 单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
var="llang is $LANG"
则
echo $var
可得
lang is $LANG
4 可用转意符 \ 将特殊符号(如 [Enter], 空格符, 等)变成一般字符;
5 在一串命令中,还需要藉由其他的命令提供的信息,可以使用反单引号 命令
或$(命 令)(推荐这种)。特别注意,那个反引号 是键盘上方癿数字键1` 左边那个按键,而不是单引号!
例如想要取得
核心版本的内容:
[root@localhost ~]# version=$(uname -r)
[root@localhost ~]# echo $version
3.10.0-693.el7.x86_64
6 增加变量的内容时,则可用 "{变量}字符串 (推荐)累加内容,如下所示:
PATH="$PATH":/home/bin
PATH=${PATH}:/home/bin
7 若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量:
export PATH
8 通常大写字符为系统默认变量,自定义变量可以使用小写字符,方便判断 (纯粹个人习惯) ;
9 取消变量的方法为使用 unset :unset 变量名称 例如取消 myname 的设定:
unset myname
三、 环境变量
这种变量是会影响bash环境操作的,会在真正进入系统前由一个bash程序读入到系统中。通常都环境变量的名字以大写字符命名。
常见环境变量
PATH HOME MAIL SHELL PWD USERNAME UID ID 等。
RANDOM 随机数
echo $RANDOM
12156
echo $RANDOM
13423
PS1:(提示字符的设置)
\d :可显示出“星期 月 日”的日期格式,如:"Mon Feb 2"
\H :完整的主机名称。如 www.sharkyun.com
\h :仅取主机名称在第一个小数点之前的名字, www
\t :显示时间,为 24 小时格式的“HH:MM:SS”
\T :显示时间,为 12 小时格式的“HH:MM:SS”
\A :显示时间,为 24 小时格式的“HH:MM”
@ :显示时间,为 12 小时格式的“am/pm”样式
\u :目前使用者的帐号名称,如“dmtsai”;
\v :BASH 的版本信息
\w :完整的工作目录名称,由根目录写起的目录名称。
但主文件夹会以 ~ 取代;
\W :利用 basename 函数取得工作目录名称,所以
仅会列出最后一个目录名。
.# :下达的第几个指令。
读取环境变量的值
echo $HOME
列出shell环境下的所有环境变量及其内容
env // env 是 environment (环境) 的简写,默认的环境变量
set // 列出系统中所有的变量,包括自定义的变量
export 变量名 // 使自定义的变量 成为 环境变量,环境变量可以被继承
子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定义变量
没有使用export
[root@localhost ~]# a=1
[root@localhost ~]# echo $a
1
[root@localhost ~]# bash #开启子进程
[root@localhost ~]# echo $a
#未被赋值
使用export
[root@localhost ~]# export a
[root@localhost ~]# bash
[root@localhost ~]# echo $a
1 #被赋值
bash 的环境变量文件
一 、longin shell
取得shell时需要完整的登入流程;特点是登入时需要用户帐号和密码
二、non-login shell
取得shell时不需要再次输入帐号和密码的情况下,所得到的 shell
longin shell 会读取以下两个文件:
1 ·/etc/profile· :这是系统整体设定,最好不要修改
2 . /.bash_profile或/.bash_login或~/.profile` :属于个人的配置文件
/etc/profile 会主动依序调用以下脚本文件:
/etc/inputrc :定义快捷键
/etc/profile.d/*sh :定义bash操作接口颜色、语系、命令别名等
etc/locale.conf :定义系统的默认语系
bash 在读完 /etc/profile 后,接下来会读取以下3个文件, 且只会读去一个,会按照以下顺序优先读取
~/.bash_profile //会调用 ~/.bashrc ,
也会有新的环境变量在下面的文件中被添加
~/.bash_login
~/.profile
最终,~/.bashrc 才是最后被读入到系统环境中的文件
让这些环境变量文件中的变量等设置及时在当前 shell 终端中生效,有下两种方式
1 source ~/.bashrc
2 .~/.bashrc
no-longin shell 当取得 no-longin shell 时,该 shell 仅会读取 ~/.bashrc 文件 而~/.bashrc 最后又会调用 /etc/bashrc
/etc/bashrc 的作用:
• 依据不同的UID定义出 umask 值
• 依据不同的UID定义出提示符(就是PS1变量)
• 呼叫 /etc/profile.d/*.sh 的设定
其他的相关配置文件
• /etc/man.config
这个文件最重要的就是定义了MANPATH 这个变量,它定义了man page 的路径;在以tarball的方式安装软件时有用
• ~/.bash_history
历史命令记录文件;记录的数量与HISTFILESIZE变量有关。在/etc/profile里
• ~/.bash_logout
记录了当我注销bash后,系统再帮我做完什么动作后才离开的。
四、预定义变量
预定义的特殊变量有着特殊的含义,用户不可以更改,所有的预定义变量都由 $ 符号和另外一个符号组成,常用的预定义特殊变量如下:
1 $! 上一个后台命令对应的进程号
2 $? 上一个命令的退出状态,为十进制数字,如果返回为0,则代表执行成功,则否为不成功。
$$ 当前的进程号PID
以上变量请配合 echo 使用,例如:
echo $!
echo $$
echo $?
位置变量
位置变量也属于预定义的变量
位置变量针对于脚本来说
# $0 程序名称,脚本的文件名
# $1 执行脚本时,跟到脚本后面的第一个参数
# $2...
# $# 位置变量的个数
# $@ 所有的位置变量的值
脚本如下
echo "$0"
echo "$1"
echo "$2"
echo "位置参数的个数为$#"
echo "所有参数是$@"
执行后
[root@localhost ~]# sh abc.sh 121243435dsfuh
abc.sh
121243435dsfuh
~
位置参数的个数为1
所有参数是121243435dsfuh
有什么用呢?比如我想计算 任意 2 个数的商数和余数,可以这么写
脚本内容
echo "商数: $(( $1 / $2 ))"
echo "余数: $(( $1 % $2 ))"
使用
[root@kube-master script]# sh jia.sh 10 3
商数: 3
余数: 1
五、变量键盘读取、数组与宣告:read, array, declare
read
[root@www ~]# read [-pt] variable
选项不参数:
-p :后面可以接提示字符!
-t :后面可以接等待的『秒数!』这个比较有趣~不会一直等待使用者啦!
如:
#vi read.sh
read -p “请输入你的姓名” name
echo "你的姓名是: $name"
数组 (array) 变量类型
数组的索引只能是数字
var=(wukong bajie shaseng)
echo ${var [2]} //显示某一个
输出 bajie
echo ${var [*]} //显示数组的全部内容
输出 wukong bajie shaseng
declare 声明关联数组
declare -A
declare -A info 声明关联数组
info[name]=shark 添加索引 name 其对应的值是 shark
info=([age]=18 [hobby]="mv rmb") 一次添加多个索引和值
echo ${info[name]} 显示出名字
echo ${info[@]} 显示出所有的值
echo ${!info[@]} 显示所有的索引
六、变量内容的删除、取代与替换
删除
先让小写的 path 自订变量设置的与 PATH 内容相同
[dmtsai@study ~]$ path=${PATH}
[dmtsai@study ~]$ echo ${path}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/shark/bin
1、删除最后一个
echo ${path%:*}
(%)从字符串的后面开是进行匹配删除,但匹配到第一个时就结束匹配。
:* 就是需要进行匹配的字符串 , : 是普通字符串 * 是通配符,代表任何数量的任意字符串。
所以下面的红色字体的字符串将会匹配后进行删除
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/shark/bin
2、删除第一个
echo ${path#*:}
(#) 是从前面开始匹配删除,匹配到道理和上面的 % 同样的道理
${path#*:} 就是 从变量值的最前面开始匹配,直到遇到第一个 : 结束
所以下面的红色字体会被匹配后删除
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/shark/bin
取代和替换
使用时要注意,如果str被先赋值,var继承str的值,var str都不被expr赋值
如
[root@localhost ~]# a=1
[root@localhost ~]# b=2
[root@localhost ~]# a=${b:-3}
[root@localhost ~]# echo $a
2
[root@localhost ~]# echo $b
2
[root@localhost ~]#
[root@localhost ~]# a=1
[root@localhost ~]# a=${b:-3}
[root@localhost ~]# echo $a
3
七、时间运算
date +%T -d '3 hours'
// 任意日期的前 N 天,后 N 天的具体日期
date +%F -d "20190910 1 day"
date +%F -d "20190910 -1 day"
// 计算两个日期相差天数, 比如计算生日距离现在还有多少天
d1=$(date +%s -d 20180728)
d2=$(date +%s -d 20180726)
echo $(( (d1-d2) / 86400 ))
# 输出
2
正则表达式RE
什么是正则表达式
简单的说,正则表达式就是处理字串的方法,他是以行为单位来进行字串的处理行为, 正则表达式通过一些特殊符号的辅助,可以让使用者轻易的达到“搜寻/删除/取代”某特定字串的处理程序!
正则表达式基本上是一种“表达式”, 只要工具程序支持这种表达式,那么该工具程序就可以用来作为正则表达式的字串处理之用。 例如 vi, grep, awk ,sed 等等工具,因为她们有支持正则表达式, 所以,这些工具就可以使用正则表达式的特殊字符来进行字串的处理。但例如 cp, ls 等指令并未支持正则表达式, 所以就只能使用 Bash 自己本身的通配符而已。
是 Linux 基础当中的基础,如果学成了之后,一定是“大大的有帮助”的!这就好像是金庸小说里面的学武难关:任督二脉! 打通任督二脉之后,武功立刻成倍成长!
关于语系
在英文大小写的编码顺序中,zh_TW.big5 及 C 这两种语系的输出结果分别如下:
1、LANG=C 时:0 1 2 3 4 ... A B C D ... Z a b c d ...z
2、LANG=zh_TW 时:0 1 2 3 4 ... a A b B c C d D ... z Z
尤其要记住:
[:alnum] 代表所有的大小写英文字符和数字 0-9 A—Z a-z
[:alpha:] 代表任意英文大小写字符 A-Z a-z
[:lower:] 代表小写字符 a-z
[:upper:] 代表大写字符 A-Z
[:digit:] 代表数字 0-9
如
grep "[[:alnum:]]" asd.txt
grep "[[:lower:]]" asd.txt
^ word 搜寻字符串(word)在行首的行
如
grep -n '^#' asd.txt
word$ 搜寻的字符串(word)在行尾的行
如
grep -n '!$' asd.txt
. 代表【一定有一个任意字符】
如
grep -n 'e.e' asd.txt
\跳脱字符,将特殊符号的特殊意义去除
如
grep -n \' asd.txt
*重复零个到无穷多个的前面一个RE字符
如
grep -n 'ess*' asd.txt
还有下面一些
[abc] 从中字符串中任意一个
[^abc] 取反
[1-9] 、[a-z]、[A-Z]1到9任意一个数字或字母
{n,m} 取连续的n个到m个前面字符
如
grep -n go"\{2,3\}"d asd.txt
取含有 good 或 goood的行
进阶 grep
-A n 把匹配成功行之后的n行也同时列出。 A 就是 after 的首字母
就是 之后 的意思
-B n 把匹配成功行之前的n行也同时列出。B 就是 before 的首字母
就是 之前 的意思
范例:
显示 /etc/passwd 含有 mail 的行及其前2行和后 3 行
[root@e9818e4ea8b3 ~]# grep mail -B 2 -A3 /etc/passwd
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
显示 目标行(这里是含有 mail 字符)的 前 后 各 3 行
grep mail -C 3 /etc/passwd
只显示匹配到的字符
grep -o 'nologin' /etc/passwd
加上统计数量
grep -o -c 'nologin' /etc/passwd
只要文件名
grep -l 'nologin' /etc/passwd
递归查找,就是在一个目录下查找
grep -r 'nologin' /etc/
搜索 test 或 taste
grep -n 't[ae]st' regular_repress.txt
搜索 oo 但其前面不要有g
grep -n '[^g]oo' regular_repress.txt
注意:当搜索的行内含有要符合搜索条件时后,此行就会忽略 明确不要的条件,比如以上的例子就可能会搜索到下面的内容
3:tool is a good tool
8:goooooogle
显示oo 前面非小写字符的行
方法一:
grep -n ‘[^a-z]oo’ regular_repress.txt
方法二:
grep -n ‘[^[:lower:]]oo’ regular_repress.txt
显示开头不是 英文字符的行
grep -n ‘^[^[:alpha]]’ regular_repress.txt
符号 ^ 在 [] 内时是取反的意思,在 [] 之外是行首的意思
显示行首不是#和;的行
grep '^[^#;]' regular_repress.txt
找到以 . 结尾的行
grep -n ‘\.$’ regular_repress.txt
需要用 \ 进行转意
查找 开头是 g 和结尾也是 g ,中间的字符可有可无
grep -n 'g.*g' regular_repress.txt
. 代表一个任意字符
- 代表重复零到多个在 其前面的一个字符
.* 代表零个或多个任意字符
查找以a为开头的任意文件名
方法一
ls -l a*
方法二
ls |grep -n ‘^a.*’
列出 /etc 目录下的链接文件
ls -l /etc |grep ‘^l’ |wc -l
扩展正则
支持扩展正则的工具
grep -E
egrep
sed
awk
正则高级部分: 贪婪|非贪婪(扩展)
贪婪 就是尽可能的多匹配
非贪婪 就是尽可能的少匹配,只需要在一些表示量词(就是次数)的后面加上 ?, 比如: .*? +?
grep 实现非贪婪
grep 或者 egrep 默认都是贪婪模式,不支持非贪婪模式。
要想实现非贪婪需要使用 -P 参数,这会使用 Perl 语言环境的正则
Perl 语言中:
\w 表示任意 一个 大小写字母 [a-zA-Z] 、下划线 _ 和数字 [0-9]
\d 表示任意 一个 数字 [0-9]
当然这些规则适用于大部分的 编程语言,比如 python java javascript go php 等。