这里是一段防爬虫文本,请读者忽略。
本文原创首发于CSDN,作者IDYS
博客首页:https://blog.csdn.net/weixin_41633902/
本文链接:https://blog.csdn.net/weixin_41633902/article/details/108446460
未经授权,禁止转载!恶意转载,后果自负!尊重原创,远离剽窃!
shell
类型[root@dayuanshuai ~] cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
echo
命令
-n
:输出内容不换行-e
:开启反斜杠转义字符关闭TAB补全时的提示音
[root@dayuanshuai ~] vim /etc/inputrc
# do not bell on tab-completion
# set bell-style none前面的\#号即可关闭TAB补全时的提示音
# set bell-style none
set meta-flag on
set input-meta on
set convert-meta off
set output-meta on
# Completed names which are symbolic links to
# directories have a slash appended.
echo
可以输出带有颜色的字符[root@dayuanshuai ~] echo -e "\e[1;33m abcd \e[0m"
abcd
\e[1是标准格式,代表颜色输出开始,\e[0m代表颜色输出结束,31m=红色,30m=黑色,32m=绿色,33m=黄色,34m=蓝色,35m=洋红,36m=青色,37m=白色
[root@dayuanshuai ~] echo -e "\e[1;45m idys \e[0m"
idys
这条命令会给 idys 加入一个洋红色的背景。echo 可以使用的背景颜色如下:40m=黑色,41m=红色, 42m=绿色,43m=黄色,44m=蓝色,45m=洋红,46m=青色,47m=白色。
sh
程序[dayuanshuai@dayuanshuai idys_learn_sh] vim ys_01_a_simple.sh
echo
#!/bin/bash
# author: idys
# date:2020-5-18
# description: print a char
echo '-------------------- program start ---------------------------'
echo 'hello!,i am idys!'
echo '-------------------- program start ---------------------------'
# 检查是否有语法错误
[dayuanshuai@dayuanshuai idys_learn_sh] bash -n ys_01_a_simple.sh
执行程序
# 给程序添加执行权限
[dayuanshuai@dayuanshuai idys_learn_sh] chmod u+x ./ys_01_a_simple.sh
[dayuanshuai@dayuanshuai idys_learn_sh] ./ys_01_a_simple.sh
-------------------- program start ---------------------------
hello!,i am idys!
-------------------- program start ---------------------------
./ys_01_a_simple.sh
:相对路径~/idys_learn_sh/ys_01_a_simple.sh
:绝对路径执行Bash
调用执行脚本
bash ys_01_a_simple.sh
[dayuanshuai@dayuanshuai idys_learn_sh] bash ys_01_a_simple.sh
-------------------- program start ---------------------------
hello!,i am idys!
-------------------- program start ---------------------------
history
:历史命令查看
-c
: 清空内存中的历史命令-w
:把缓存中的历史命令写入历史命令保存文件。如果不手工指定历史命令保存文件,则放入默认历史命令保存文件~/.bash_history
中,这种方式相当于将内存中的历史命令直接覆盖保存至~/.bash_history
文件中,如果你清空缓存中的命令再来执行history -w
命令,那么~/.bash_history
文件中以前保存信息都会清除-a
: 追加缓存中执行的历史命令到历史文件~/bash_history
中-s
:伪造历史命令,比如使用history -s mkdir mysql
那么,会向历史命令中添加mkdir mysql
这条命令,但是不会执行mkdir mysql
命令-r
:读取历史文件中的所有命令到内存中的历史列表-d #
:删除缓存中记录的第多少条命令关于命令历史的几个环境变量
HISTSIZE
:定义内存中历史命令保存条数HISTFILESIZE
:定义命令历史文件中保存命令的条数HISTFILE
:定义命令历史文件保存的位置[dayuanshuai@dayuanshuai idys_learn_sh] set | grep HIST
HISTCONTROL=ignoredups
HISTFILE=/home/dayuanshuai/.bash_history
HISTFILESIZE=1000
HISTSIZE=1000
!n
执行第 n 条历史命令!!
执行上一条命令!STRING
执行最后一条以该字串开头的命令!$
上一条命令的最后一个参数.
. /.bashrc
这个前面的.
相当于source.bashrc
相当于隐藏文件./mydir
:这个斜杠/
前面的.
相当于当前目录下$PATH
环境变量定义的目录查找顺序,执行找到的第一个命令~/.bashrc
。命令如下:vi /root/.bashrc
hash
概念PATH
路径下寻找。hash表的作用:大大提高命令的调用效率。同时需要注意的是:如果hash表中记录了该命令的映射时,那么再次执行该命令时,linux会直接从hash表中取出映射对应的命令所在位置,而不是去$PATH环境变量中逐个查找命令文件。如果我们把一个已经执行过的命令从环境变量的一个目录位置移到另外一个位置,虽然都是在环境变量中,但是当我们再次执行命令时,Linux就会报错,因为它已经在hash表中建立映射路径,当那个路径中没有这个命令文件时,它就会直接报错,而不是到环境变量中再查找执行命令。
# 首先执行cat命令
[root@dayuanshuai ~] cat /etc/profile
# /etc/profile
# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/
..... 后面的省略
# 查看hash表,发现hash表中有cat对于的命令执行路径
[root@dayuanshuai ~] hash -l
builtin hash -p /usr/bin/pstree pstree
builtin hash -p /usr/bin/head head
builtin hash -p /bin/rm rm
builtin hash -p /bin/cat cat
builtin hash -p /bin/sh sh
builtin hash -p /bin/cp cp
builtin hash -p /usr/bin/man man
builtin hash -p /bin/ls ls
builtin hash -p /bin/su su
# 打印PATH环境变量的值
[root@dayuanshuai ~] echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
# 将cat命令文件从/bin移动到/usr/bin下,注意/bin和/usr/bin都在环境变量中
[root@dayuanshuai ~] mv /bin/cat /usr/bin/
# 此时再次执行cat就会报错
[root@dayuanshuai ~] cat /etc/profile
-bash: /bin/cat: 没有那个文件或目录
# 清空hash表再次执行cat就会成功
[root@dayuanshuai ~] hash -r
# 可以看到cat执行成功
[root@dayuanshuai ~] cat /etc/issue
CentOS release 6.10 (Final)
Kernel \r on an \m
-l
显示hash表内容-r
清除hash表-d cat
删除表中某一条(删除cat)-t cat
查看openssl命令路径(hash表中没有的话,可以调用which命令)-p /bin/cat mycat
往hash
表中添加一条,执行mycat
即执行cat
命令(起别名)快捷键 | 作用 |
---|---|
ctrl+A | 把光标移动到命令行开头。如果我们输入的命令过长,想要把光标移 动到命令行开头时使用 |
ctrl+E | 把光标移动到命令行结尾 |
ctrl+C | 强制终止当前的命令 |
ctrl+L | 清屏,相当于 clear 命令 |
ctrl+U | 删除或剪切光标之前的命令 |
ctrl+K | 删除或剪切光标之后的内容 |
ctrl+Y | 粘贴 ctrl+U 或 ctrl+K 剪切的内容 |
ctrl+R | 在历史命令中搜索,按下 ctrl+R 之后,就会出现搜索界面,只要输入搜索内容,就会从历史命令中搜索 |
ctrl+D | 退出当前终端 |
ctrl+Z | 暂停,并放入后台 |
ctrl+S | 暂停屏幕输出 |
ctrl+Q | 恢复屏幕输出 |
设备 | 设备文件名 | 文件描述符 | 类型 |
---|---|---|---|
键盘 | /dev/stdin | 0 | 标准输入 |
显示器 | /dev/stdout | 1 | 标准输出 |
显示器 | /dev/stdout | 2 | 标准错误输出 |
命令 > 文件
命令 >> 文件
错误命令 2> 文件
错误命令 2>> 文件
命令 > 文件 2>&1
命令 >> 文件 2>&1
命令 &> 文件
命令 &> 文件
命令 &>> 文件
命令 1>> 文件 2>>文件2
wc [OPTIONS] [FILENAME]
-c
统计字节数-w
统计单词数-l
统计行数# 统计两个EOF之间的行数,单词数,字节数(用EOF做分隔)
[dayuanshuai@dayuanshuai idys_learn_sh] wc << EOF
> who am i
> your name
> is
> and
> EOF
4 7 27
多命令执行符 | 格式 | 作用 |
---|---|---|
; | 命令1;命令2 | 多个命令顺序执行,命令之间没有任何逻辑联系 |
&& | 命令1 && 命令2 | 当命令1 正确执行($?=0),则命令2 才会执行 当命令 1 执行不正确($? ≠ 0),则命令 2 不会执行 |
|| | 命令1 || 命令2 | 当命令 1 执行不正确($? ≠ 0),则命令 2 才会执行 当命令 1 正确执行($?=0),则命令 2 不会执行 |
#命令正确执行显示yes,错误执行显示no
[dayuanshuai@dayuanshuai idys_learn_sh] whoami1 &>/dev/null && echo yes || echo no
no
[dayuanshuai@dayuanshuai idys_learn_sh] whoami &>/dev/null && echo yes || echo no
yes
grep
选项 | 含义 |
---|---|
-A # | 列出符合条件的行,并列出后续的n行 |
-B # | 列出符合条件的行,并列出前面的n行 |
-c | 统计找到的符合条件的字符串的次数 |
-i | 忽略大小写 |
-n | 输出行号 |
-v | 反向查找 |
–color=auto | 搜索出的关键词用颜色显示 |
# 查找不含有 /bin/bash的用户,其实就是查找伪用户
[dayuanshuai@dayuanshuai idys_learn_sh] grep --color -v "/bin/bash" /etc/passwd
find与grep
# 查找/etc/ 下以.conf结尾,大于5k,的普通文件
[dayuanshuai@dayuanshuai idys_learn_sh] find /etc/ -type f -size +5k -name "*.conf" -exec ls -lh {
} \; &>./2.txt | grep -v "Permission denied" ./2.txt
-rw-r--r--. 1 root root 5.8K Mar 22 2017 /etc/modprobe.d/dist.conf
-rw-r--r--. 1 root root 5.3K May 27 2014 /etc/fonts/fonts.conf
-rw-r--r--. 1 root root 7.6K May 27 2014 /etc/fonts/conf.avail/65-nonlatin.conf
-rw-r--r--. 1 root root 9.7K May 27 2014 /etc/fonts/conf.avail/65-fonts-persian.conf
-rw-r--r--. 1 root root 83K Nov 15 2017 /etc/lvm/lvm.conf
-rw-r--r--. 1 root root 7.2K May 11 2016 /etc/dbus-1/system.d/ConsoleKit.conf
-rw-r--r--. 1 root root 8.0K Aug 31 2019 /etc/kdump.conf
find 命令是可以通过-regex 选项识别正则表达式规则的,也就是说 find 命令可以按照正则表达式规则匹配,而正则表达式是模糊匹配。
# 查看服务器建立的tcp连接
[dayuanshuai@dayuanshuai idys_learn_sh] netstat -ant | grep -i establish
Active Internet connections (servers and established)
tcp 0 96 192.168.200.141:22 192.168.200.1:10138 ESTABLISHED
通配符 | 作用 |
---|---|
? | 匹配一个任意字符 |
* | 匹配 0 个或任意多个任意字符,也就是可以匹配任何内容 |
[] | 匹配中括号中任意一个字符。例如:[abc]代表一定匹配一个字符,或者是 a,或者是 b,或者是 c。 |
[-] | 匹配中括号中任意一个字符,-代表一个范围。例如:[a-z]代表匹配一 个小写字母。 |
[^] | 逻辑非,表示匹配不是中括号内的一个字符。例如:[^0-9] 代表匹配一 个不是数字的字符。 |
符号 | 作用 |
---|---|
’ ’ | 单引号。在单引号中所有的特殊符号,如$ 和"`"(反引号)都没有特殊含义。 |
“” | 双引号。在双引号中特殊符号都没有特殊含义,但是“$”、“`”和“\” 是例外,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义。 |
`` | 反引号。反引号括起来的内容是系统命令,在 Bash 中会先执行它。和$() 作用一样,不过推荐使用$() ,因为反引号非常容易看错。 |
$() | 和反引号作用一样,用来引用系统命令。 |
{} | 用于一串命令执行时,{}中的命令会在当前 Shell 中执行。也可以用于变量变形与替换。 |
() | 用于一串命令执行时,()中的命令会在子 Shell 中运行 |
[] | 用于变量的测试。 |
# | 在 Shell 脚本中,#开头的行代表注释。 |
$ | 用于调用变量的值,如需要调用变量 name 的值时,需要用$name 的方式得到变量的值。 |
\ | 转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符。如\$ 将输出“$”符号,而不当做是变量引用。 |
()
与{}
大区别# 给变量myname赋值idys
[root@dayuanshuai ~] myname=idys
# 给该shell的子shell赋值dayuanshuai,然后再打印输出
[root@dayuanshuai ~] ( myname=dayuanshuai;echo $myname )
dayuanshuai
# 这时你再打印myname的值,你会发现myname的值仍然为idys
[root@dayuanshuai ~] echo $myname
idys
# 通过大括号圈起来,将 dayuanshuai赋值给myname
[root@dayuanshuai ~] {
myname=dayuanshuai;echo $myname;}
dayuanshuai
# 这次再次打印 myname 你会发现myname的值已经变为dayuanshuai了
[root@dayuanshuai ~] echo $myname
dayuanshuai
()最后一个命令可以不用分号“;”,而{}中最后一个命令必须用“ ;”
"$变量名"
或用${变量名}
包含变量名[root@dayuanshuai ~] words="who am"
[root@dayuanshuai ~] echo $words
who am
[root@dayuanshuai ~] words="$words i"
[root@dayuanshuai ~] echo $words
who am i
[root@dayuanshuai ~] words=${words}hhh
[root@dayuanshuai ~] echo $words
who am ihhh
变量值的叠加可以使用两种格式:
“$变量名”
或${变量名}
[root@dayuanshuai ~] linux_release=`cat /etc/centos-release`
[root@dayuanshuai ~] echo $linux_release
CentOS release 6.10 (Final)
[root@dayuanshuai ~] linux_release_2=$( cat /etc/issue )
[root@dayuanshuai ~] echo $linux_release_2
CentOS release 6.10 (Final) Kernel \r on an \m
set
命令选项 | 作用 |
---|---|
-u | 如果设定此选项,调用未声明变量时会报错(默认无任何提示) |
-x | 如果设定此选项,在命令执行之前,会把命令先输出一次 |
set不加任何选项 | 直接使用set命令,会查询系统中所有的变量,包含用户自定义变量和环境变量 |
# 因为myage变量没有定义,所以打印myage没有任何输出
[root@dayuanshuai ~] echo $myage
# 使用set -u 选项,当调用没有声明的变量时会报错
[root@dayuanshuai ~] set -u
[root@dayuanshuai ~] echo $myage
-bash: myage: unbound variable
# 取消set的u选项
[root@dayuanshuai ~] set +u
# 设置 x 选项
[root@dayuanshuai ~] set -x
# 此时执行ll命令时会把命令输出一遍
[root@dayuanshuai ~] ll
+ ls --color=auto -l --color=auto
total 24
-rw-------. 1 root root 943 Aug 31 2019 anaconda-ks.cfg
-rw-r--r--. 1 root root 13195 Aug 31 2019 install.log
-rw-r--r--. 1 root root 3482 Aug 31 2019 install.log.syslog
env
:查看环境变量(不包括自定义变量)[root@dayuanshuai ~] env
HOSTNAME=dayuanshuai
SELINUX_ROLE_REQUESTED=
TERM=linux
unset
删除环境变量[root@dayuanshuai ~] myname=idys
[root@dayuanshuai ~] echo $myname
idys
[root@dayuanshuai ~] unset myname
[root@dayuanshuai ~] echo $myname
# 定义环境变量
[root@dayuanshuai ~] export myname=idys
# 定义用户自定义变量
[root@dayuanshuai ~] age=18
# 在当前shell中打印age和myname的值
[root@dayuanshuai ~] echo $age
18
[root@dayuanshuai ~] echo $myname
idys
# 在子shell中再次打印age和myname的值,发现age的值消失了
[root@dayuanshuai ~] bash
[root@dayuanshuai ~] echo $age
[root@dayuanshuai ~] echo $myname
idys
env
命令可以查询到所有的环境变量,可是还有一些变量虽然不是环境变量,却是和 Bash 操作接口相关的变量,这些变量也对我们的 Bash 操作终端起到了重要的作用。这些变量就只能用 set 命令来查看了[root@dayuanshuai ~] set
BASH=/bin/bash # 所使用的bash shell类型
BASH_VERSION='4.1.2(2)-release' #bash版本
COLORS=/etc/DIR_COLORS #颜色记录文件
PATH
变量:系统查找命令的路径PS1
变量:命令提示符设置,PS1
可以支持以下这些选项:选项 | 含义 |
---|---|
\d |
显示日期,格式为“星期 月 日” |
\H |
显示完整的主机名。如默认主机名“localhost.localdomain” |
\h |
显示简写主机名。如默认主机名“localhost” |
\t |
显示 24 小时制时间,格式为“HH:MM:SS” |
\A |
显示 24 小时制时间,格式为“HH:MM” |
\T |
显示 12 小时制时间,格式为“HH:MM:SS” |
\@ |
格式为“HH:MM am/pm” |
\u |
显示当前用户名 |
\v |
显示 Bash 的版本信息 |
\w |
显示当前所在目录的完整名称 |
\W |
显示当前所在目录的最后一个目录 |
\# |
执行的第几个命令 |
\$ |
提示符。如果是 root 用户会显示提示符为“#”,如果是普通用户会显示提示符为"$" |
查看PS1
的值
[root@IDYS /]# echo $PS1
[\u@\h \W]\$
修改PS1
的值
[root@IDYS /]# PS1='[\u@\H \w]\$ '
环境变量配置文件有
/etc/bashrc
~/.bashrc
/etc/profile
/etc/profile.d/*.sh
~/.bashrc_profile
修改Linux系统默认使用的语言
[root@IDYS /usr/local/src]# ls -l /root
总用量 20
-rw-------. 1 root root 921 4月 28 17:32 anaconda-ks.cfg
-rw-r--r--. 1 root root 9430 4月 28 17:32 install.log
-rw-r--r--. 1 root root 3161 4月 28 17:31 install.log.syslog
[root@IDYS /usr/local/src]# echo $LANG #查看当前系统使用的默认语言
zh_CN.utf8
[root@IDYS /usr/local/src]# LANG='en_US.utf8' # 修改系统默认语言
[root@IDYS /usr/local/src]# ls -l /root # 现在再次查看显示效果
total 20
-rw-------. 1 root root 921 Apr 28 17:32 anaconda-ks.cfg
-rw-r--r--. 1 root root 9430 Apr 28 17:32 install.log
-rw-r--r--. 1 root root 3161 Apr 28 17:31 install.log.syslog
位置参数变量 | 作用 |
---|---|
$n |
n 为数字,$0 代表命令本身,$1 - $9 代表第一到第九个参数,十以上的参数需要用大括号包含,如${10} . |
$* |
这个变量代表命令行中所有的参数,$* 把所有的参数看成一个整体 |
$@ |
这个变量也代表命令行中所有的参数,不过$@ 把每个参数区分对待 |
$# |
这个变量代表命令行中所有参数的个数 |
$()
:括系统命令$(())
:用于执行变量加减,复制$@
和$*
的区别,以下我通过代码的演示区别#!/bin/bash
# encoding=utf-8
function comtwo()
{
echo "**********************使用\"\$*\"*************************"
for i in "$*"
do
echo "$i"
done
echo ""
echo "**********************使用修改后的\"\$*\"*****************"
for i in "$*"
do
echo "$i" | tr " " "\n"
done
echo ""
echo "**********************使用\"\$@\"*************************"
for i in "$@"
do
echo "$i"
done
}
echo ""
comtwo $@
[dayuanshuai@IDYS sh_day01]$ bash comtwo.sh 11 22 33 44 55 66
**********************使用"$*"*************************
11 22 33 44 55 66
**********************使用修改后的"$*"*****************
11
22
33
44
55
66
**********************使用"$@"*************************
11
22
33
44
55
66
预定义变量 | 作 用 |
---|---|
$? |
最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。 |
$$ |
当前进程的进程号(PID) |
$! |
后台运行的最后一个进程的进程号(PID) |
[dayuanshuai@IDYS sh_day01]$ ls ./
comtwo.sh count.sh countv2.sh testnet.sh
[dayuanshuai@IDYS sh_day01]$ echo $?
0
[dayuanshuai@IDYS sh_day01]$ ls asdas
ls: cannot access asdas: No such file or directory
[dayuanshuai@IDYS sh_day01]$ echo $?
2
[dayuanshuai@IDYS sh_day01]$ echo $$
5712
[dayuanshuai@IDYS sh_day01]$ top &
[1] 5906
[dayuanshuai@IDYS sh_day01]$ echo $!
5906
[1]+ Stopped top
[dayuanshuai@IDYS sh_day01]$ ps
PID TTY TIME CMD
5712 pts/1 00:00:00 bash
5906 pts/1 00:00:00 top
5907 pts/1 00:00:00 ps
read
命令
read
[选项] [变量名]
[选项]
-p “提示信息”
: 在等待 read 输入时,输出提示信息-t 秒数
: read 命令会一直等待用户输入,使用此选项可以指定等待时间-n 字符数
: read 命令只接受指定的字符数,就会执行-s
: 隐藏输入的数据,适用于机密信息的输入变量名:
如果我需要进行数值运算,可以采用以下三种方法中的任意一种:
既然所有变量的默认类型是字符串型,那么只要我们把变量声明为整数型不就可以运算了吗?使用declare
命令就可以实现声明变量的类型。命令如下:
declare
[+/-]
[选项]
变量名选项 | 含义 |
---|---|
- |
给变量设定类型属性 |
+ |
取消变量的类型属性 |
-a |
将变量声明为数组型 |
-i |
将变量声明为整数型(integer) |
-r |
讲变量声明为只读变量。注意,一旦设置为只读变量, 既不能修改变量的值, 也不能删除变量,甚至不能通过 +r 取消只读属性 |
-x |
将变量声明为环境变量 |
-p |
显示指定变量的被声明的类型 |
[root@IDYS ~] num1=11
[root@IDYS ~] num2=22
[root@IDYS ~] declare -i sum=num1+num2
[root@IDYS ~] echo $sum
33
[dayuanshuai@IDYS sh_day01]$ system[0]=unix
[dayuanshuai@IDYS sh_day01]$ system[1]=linux
[dayuanshuai@IDYS sh_day01]$ system[2]=Windows
# 定义一个数组,第一个元素为unix,第二个元素Linux,第三个元素Windows
[dayuanshuai@IDYS sh_day01]$ echo ${system}
unix
[dayuanshuai@IDYS sh_day01]$ echo ${system[0]}
unix
[dayuanshuai@IDYS sh_day01]$ echo ${system[2]}
Windows
[dayuanshuai@IDYS sh_day01]$ echo system[0]
system[0]
我们其实也可以使用 declare 命令把变量声明为环境变量,和 export 命令的作用是一样的:
[dayuanshuai@IDYS sh_day01]$ declare -p test #查看test变量的被声明类型
-bash: declare: test: not found
[dayuanshuai@IDYS sh_day01]$ declare -x test="123" #将test 声明为环境变量
[dayuanshuai@IDYS sh_day01]$ declare -p test
declare -x test="123"
[dayuanshuai@IDYS sh_day01]$ declare +x test="123" #取消test为环境变量
[dayuanshuai@IDYS sh_day01]$ declare -p test
declare -- test="123"
[dayuanshuai@IDYS sh_day01]$ unset test #取消变量声明
[dayuanshuai@IDYS sh_day01]$ declare -p test
-bash: declare: test: not found
[dayuanshuai@IDYS sh_day01]$ export test="456" #将test设为环境变量
[dayuanshuai@IDYS sh_day01]$ declare -p test
declare -x test="456"
[dayuanshuai@IDYS sh_day01]$ declare -ar test="0" #将test设置为只读
-bash: test: readonly variable
[dayuanshuai@IDYS sh_day01]$ test=23
-bash: test: readonly variable
[dayuanshuai@IDYS sh_day01]$ echo $test
[dayuanshuai@IDYS sh_day01]$ declare -p test
declare -ar test='()'
[dayuanshuai@IDYS sh_day01]$ declare +r test
-bash: declare: test: readonly variable
[dayuanshuai@IDYS sh_day01]$ unset test
-bash: unset: test: cannot unset: readonly variable
重新登录或重启,这个变量就会消失了。
[dayuanshuai@IDYS sh_day01]$ declare -p
***************
declare -x TERM="linux"
declare -ir UID="500"
declare -x USER="dayuanshuai"
declare -- _="test"
declare -- colors="/etc/DIR_COLORS"
declare -- num="0"
declare -- sum="0"
declare -a system='([0]="unix" [1]="linux" [2]="Windows")'
declare -ar test='()'
[dayuanshuai@IDYS sh_day01]$ declare -p test
declare -ar test='()'
[dayuanshuai@IDYS sh_day01]$ declare -p system
declare -a system='([0]="unix" [1]="linux" [2]="Windows")'
expr
或 let
数值运算工具[dayuanshuai@IDYS ~]$ num1=11
[dayuanshuai@IDYS ~]$ num2=22
[dayuanshuai@IDYS ~]$ dd=$(expr $num1 + $num2) #dd 的值是 num1 和 num2 的和。注意“+”号左右两侧必须有空格
[dayuanshuai@IDYS ~]$ echo $dd
33
使用
expr
命令进行运算时,要注意+
号左右两侧必须有空格,否则运算不执行。 至于let
命令和expr
命令基本类似,都是Linux
中的运算命令,命令格式如下
[dayuanshuai@IDYS ~]$ num1=11
[dayuanshuai@IDYS ~]$ num2=22
[dayuanshuai@IDYS ~]$ let sum=$num1+$num2
[dayuanshuai@IDYS ~]$ echo $sum
33
[dayuanshuai@IDYS ~]$ n=20
[dayuanshuai@IDYS ~]$ let n+=1
[dayuanshuai@IDYS ~]$ echo $n
21
expr
命令和let
命令大家可以按照习惯使用,不过let
命令对格式要求要比expr
命令宽松,所 以推荐使用let
命令进行数值运算。
$((运算式))
或$[运算式]
方式运算 其实这是一种方式$(())
和$[]
这两种括号按照个人习惯使用即可。命令如下[dayuanshuai@IDYS ~]$ num1=11
[dayuanshuai@IDYS ~]$ num2=22
[dayuanshuai@IDYS ~]$ sum1=$(( $num1+$num2 ))
[dayuanshuai@IDYS ~]$ echo $sum1
33
[dayuanshuai@IDYS ~]$ sum2=$[ $num1+$num2 ]
[dayuanshuai@IDYS ~]$ echo $sum2
33
推荐使用
$((运算式))
优先级 | 运算符 | 说明 |
---|---|---|
13 | - , + |
单目负、单目正 |
12 | ! , ~ |
逻辑非、按位取反或补码 |
11 | * , / , % |
乘、除、取模 |
10 | + , - |
加、减 |
9 | << , >> |
按位左移、按位右移 |
8 | < = , > = , < , > |
小于或等于、大于或等于、小于、大于 |
7 | == , != |
等于、不等于 |
6 | & |
按位与 |
5 | ^ | 按位异或 |
4 | | |
按位或 |
3 | && |
逻辑与 |
2 | || |
逻辑或 |
1 | = ,+= ,-= ,*= ,/= ,%= ,&= , ^= ,= , <<= , >>= |
赋值、运算且赋值 |
运算符优先级表明在每个表达式或子表达式中哪一个运算对象首先被求值,数值越大优先级越高,具有较高优先级级别的运算符先于较低级别的运算符进行求值运算。
[dayuanshuai@IDYS ~]$ aa=$(( (11+3)*3/2 ))
[dayuanshuai@IDYS ~]$ echo $aa
21
[dayuanshuai@IDYS ~]$ bb=$(( 17 % 3 ))
[dayuanshuai@IDYS ~]$ echo $bb
2
[dayuanshuai@IDYS ~]$ cc=$(( 11 && 1 ))
[dayuanshuai@IDYS ~]$ echo $cc
1
变量置换方式 | 变量 y没有设置 | 变量 y 为空值 | 变量 y 设置值 |
---|---|---|---|
x=${y-新值} |
x=新值 |
x 为空 |
x=$y |
x=${y:-新值} |
x=新值 |
x=新值 |
x=$y |
x=${y+新值} |
x 为空 |
x=新值 |
x=新值 |
x=${y:+新值} |
x 为空 |
x 为空 |
x=新值 |
x=${y=新值} |
x=新值 y=新值 |
x 为空 y 值不变 |
x=$y y 值不变 |
x=${y:=新值} |
x=新值 y=新值 |
x=新值 y=新值 |
x=$y y 值不变 |
x=${y?新值} |
新值输出到标准错误 输出(就是屏幕) |
x 为空 |
x=$y |
x=${y:?新值} |
新值输出到标准错误 输出 |
新值输出到标准错误输出 |
x=$y |
如果大括号内没有:
,则变量 y
是为空,还是没有设置,处理方法是不同的;如果大括号内有:
,则变量y
不论是为空,还是没有设置,处理方法是一样的。
如果大括号内是-
或+
,则在改变变量 x
值的时候,变量 y
是不改变的;如果大括号内是 =
,则在改变变量 x
值的同时,变量 y
的值也会改变。
如果大括号内是?
,则当变量 y
不存在或为空时,会把新值当成报错输出到屏幕上
[dayuanshuai@IDYS ~]$ x=${y-3}
[dayuanshuai@IDYS ~]$ echo $y
[dayuanshuai@IDYS ~]$ echo $x
3
[dayuanshuai@IDYS ~]$ y="50"
[dayuanshuai@IDYS ~]$ x=${y-3}
[dayuanshuai@IDYS ~]$ echo $x
50
[dayuanshuai@IDYS ~]$ echo $y
50
# 换另外一种形式 := 测试
[dayuanshuai@IDYS ~]$ x=${y:=10}
[dayuanshuai@IDYS ~]$ echo $x
10
[dayuanshuai@IDYS ~]$ echo $y
10
[dayuanshuai@IDYS ~]$ y=200
[dayuanshuai@IDYS ~]$ x=${y:=300}
[dayuanshuai@IDYS ~]$ echo $x
200
[dayuanshuai@IDYS ~]$ echo $y
200
# 使用 ? 继续测试
[dayuanshuai@IDYS ~]$ x=${y?4}
-bash: y: 4
[dayuanshuai@IDYS ~]$ echo $y
[dayuanshuai@IDYS ~]$ echo $x
[dayuanshuai@IDYS ~]$ y="who"
[dayuanshuai@IDYS ~]$ x=${y?4}
[dayuanshuai@IDYS ~]$ echo $x
who
[dayuanshuai@IDYS ~]$ echo $y
who
source
命令[dayuanshuai@IDYS ~]$ source 配置文件
[dayuanshuai@IDYS ~]$ . 配置文件
/etc/profile
/etc/profile.d/*.sh
~/.bash_profile
~/.bashrc
/etc/bashrc
在用户登录过程先调用/etc/profile
文件
在这个环境变量配置文件中会定义这些默认环境变量:
USER
变量:根据登录的用户,给这个变量赋值(就是让 USER 变量的值是当前用户)LOGNAME
变量:根据 USER 变量的值,给这个变量赋值。MAIL
变量:根据登录的用户,定义用户的邮箱为/var/spool/mail/
用户名。PATH
变量:根据登录用户的 UID
是否为 0
,判断 PATH 变量是否包含/sbin
、/usr/sbin
和/usr/local/sbin
这三个系统命令目录。HOSTNAME
变量:更加主机名,给这个变量赋值。HISTSIZE
变量:定义历史命令的保存条数。umask
:定义 umask 默认权限。注意/etc/profile
文件中的 umask
权限是在“有用户登录过程(也就是输入了用户名和密码)”时才会生效。/etc/profile.d/*.sh
文件,也就是调用/etc/profile.d/
目录下所有以.sh
结尾的 文件。/etc/profile
文件调用/etc/profile.d/*.sh
文件 这个目录中所有以.sh
结尾的文件都会被/etc/profile
文件调用,这里最常用的就是 lang.sh
文件,而这个文件又会调用/etc/sysconfig/i18n
文件。/etc/sysconfig/i18n
这个文件眼熟吗?就是我们前面讲过的默认语系配置文件啊/etc/profile
文件调用~/.bash_profile
文件 ~/.bash_profile
文件就没有那么复杂了,这个文件主要实现了两个功能:
~/.bashrc
文件。PATH
变量后面加入了:$HOME/bin
这个目录。那也就是说,如果我们在自己的家 目录中建立 bin
目录,然后把自己的脚本放入~/bin
目录,就可以直接执行脚本, 而不用通过目录执行了。~/.bash_profile
文件调用~/.bashrc
文件在~/.bashrc
文件中主要实现了:
/etc/bashrc
由~/.bashrc
调用了/etc/bashrc
文件
在/etc/bashrc
文件中主要定义了这些内容:
PS1
变量:也就是用户的提示符,如果我们想要永久修改提示符,就要在这个文件中修改,umask
:定义 umask
默认权限。这个文件中定义的 umask
是针对没有登录过程(也就是不需要输入用户名和密码时,比如从一个终端切换到另一个终端,或进入子 Shell)时生效的。如果是“有用户登录过程”,则是/etc/profile
文件中的 umask
生效。PATH
变量:会给 PATH
变量追加值,当然也是在“没有登录过程”时才生效。/etc/profile.d/*.sh
文件,这也是在“没有用户登录过程”是才调用。在“有用户登录过程”时,/etc/profile.d/*.sh
文件已经被/etc/profile
文件调用过了。这样这五个环境变量配置文件会被依次调用,那么如果是我们自己定义的环境变量应该放入哪个 文件呢?如果你的修改是打算对所有用户生效的,那么可以放入/etc/profile
环境变量配置文件;如果你的修改只是给自己使用的,那么可以放入~/.bash_profile
或~/.bashrc
这两个配置文件中的任一个。 可是如果我们误删除了这些环境变量,比如删除了/etc/bashrc
文件,或删除了~/.bashrc
文件, 那么这些文件中配置就会失效(~/.bashrc
文件会调用/etc/bashrc
文件)。那么我们的提示符就会 变成:
-bash-4.1#
~/.bash_logout
。这个文件默认没有写入任何内容,可是如果我们希望再退出登录时执行一些操作,比如清除历史命令,备份某些数据, 就可以把命令写入这个文件。~/bash_history
文件,也就是历史命令保存文件。Shell
登录信息/etc/issue
tty1-tty6
这六个本地终端时,会有几行的欢迎界面。这些欢迎信息是保存在哪里的? 可以修改吗?当然可以修改,这些欢迎信息是保存在/etc/issue
文件中,我们查看下这个文件:[dayuanshuai@IDYS ~] cat /etc/issue
CentOS release 6.10 (Final)
Kernel \r on an \m
man agetty
命令查询,在表中我们列出常见的转义符作用:转义符 | 作 用 |
---|---|
\d |
显示当前系统日期 |
\s |
显示操作系统名称 |
\l |
显示登录的终端号,这个比较常用 |
\m |
显示硬件体系结构,如 i386、i686 等 |
\n |
显示主机名 |
\o |
显示域名 |
\r |
显示内核版本 |
\t |
显示当前系统时间 |
\u |
显示当前登录用户的序列号 |
/etc/issue.net
/etc/issue
是在本地终端登录是显示欢迎信息的,如果是远程登录(如 ssh
远程登录,或 telnet
远程登录)需要显示欢迎信息,则需要配置/etc/issue.net
这个文件了。使用这个文件时由两点需要注意:/etc/issue
文件中支持的转义符,在/etc/issue.net
文件中不能使用。 其次,ssh
远程登录是否显示/etc/issue.net
文件中的欢迎信息,是由 ssh
的配置文件决定 的。 如果我们需要 ssh
远程登录可以查看/etc/issue.net
的欢迎信息,那么首先需要修改 ssh
的配置/etc/ssh/sshd_config
,加入如下内容:[root@IDYS ~] cat /etc/ssh/sshd_config
# no default banner path
# Banner none
Banner /etc/issue.net
这样在 ssh 远程登录时,也可以显示欢迎信息,只是不再可以识别
\d
和\l
等信息了
/etc/motd
/etc/motd
文件中也是显示欢迎信息的,这个文件和/etc/issue
及/etc/issue.net
文件的区别是: /etc/issue
及/etc/issue.net
是在用户登录之前显示欢迎信息,而/etc/motd
是在用户输入用户名和 密码,正确登录之后显示欢迎信息。在/etc/motd
文件中的欢迎信息,不论是本地登录,还是远程登录都可以显示。Bash
快捷键[root@IDYS ~] stty -a
speed 38400 baud; rows 24; columns 77; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0
ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
[root@IDYS ~] stty 关键字 快捷键
sum=0;seq 1 100 | awk '{sum+=$1}END{print sum}'
[dayuanshuai@IDYS sh_day01]$ sum=0;seq 1 10000 | awk '{sum+=$1}END{print sum}'
50005000
#!/bin/bash
# 首先判断输入的参数里面是否含有字符串
function mycount(){
i=1
while [ "$i" -le "$#" ]
do
# 现在 通过${!i}去实现第一个参数,第二个参数,第n个参数的效果
if echo ${!i} | grep -q '[^1-9]'
then
echo "your input contain str,please input again."
exit 1
fi
let i++ # 让i递增
done
i=1
while [ "$i" -le "$#" ]
do
let sum=$sum+${!i}
let i=$i+1
done
echo $sum
}
function menu(){
cat << EOF
`echo "*****************this is a counting program start***************************"`
`echo "1.对你输入的参数实行累加"`
`echo "2.不做任何操作,直接退出"`
`echo "*****************this is a counting program end*****************************"`
EOF
read -p "请输入上述编号" num
case $num in
1)
mycount $@
;;
2)
echo "正常退出程序";;
*)
echo "你输入的$num为非法输入,异常退出"
esac
}
menu $@
[dayuanshuai@IDYS sh_day01]$ ./countv2.sh 12 13 14
*****************this is a counting program start***************************
1.对你输入的参数实行累加
2.不做任何操作,直接退出
*****************this is a counting program end*****************************
请输入上述编号1
39
[dayuanshuai@IDYS sh_day01]$ ./countv2.sh 12 13 14
*****************this is a counting program start***************************
1.对你输入的参数实行累加
2.不做任何操作,直接退出
*****************this is a counting program end*****************************
请输入上述编号2
正常退出程序
[dayuanshuai@IDYS sh_day01]$ ./countv2.sh 12 13 asa
*****************this is a counting program start***************************
1.对你输入的参数实行累加
2.不做任何操作,直接退出
*****************this is a counting program end*****************************
请输入上述编号1
your input contain str,please input again.
#!/bin/bash
if [ $# -gt 3 ];
then
echo "your input over "
exit -1
fi
case $2 in
"*")
echo $(( $1 * $3 ))
;;
"/")
echo $(( $1 / $3))
;;
"+")
echo $(( $1 + $3))
;;
"-")
echo $(( $1 - $3 ))
esac
[dayuanshuai@IDYS sh_day03]$ ./four_type_count.sh 22 "*" 4
88
[dayuanshuai@IDYS sh_day03]$ ./four_type_count.sh 22 "/" 4
5
[dayuanshuai@IDYS sh_day03]$ ./four_type_count.sh 22 "+" 4
26
[dayuanshuai@IDYS sh_day03]$ ./four_type_count.sh 22 "-" 4
18
#!/bin/bash
function fourOperator(){
read -t 40 -p "请输入第一个数字" num1
read -t 40 -p "请输入第二个数字" num2
read -t 40 -p "请输入操作符" operator
if echo $num1 | grep -q '[^0-9]' || echo $num2 | grep -q '[^0-9]'
then
echo "你输入的不是一个数字,程序错误退出"
exit -1
fi
num1=`echo $num1 | sed "s/^0*//g"`
num2=`echo $num2 | sed "s/^0*//g"`
case $operator in
"+" | "-" | "*" | "/")
echo "运算结果为 $(( $num1 $operator $num2))"
;;
*)
echo "您的运算符不合法"
exit -1
esac
}
function menu(){
cat << EOF
`echo "*********************** 加减乘除运算程序开始 **********************"`
`echo "1. 输入1 进入加减乘除运算程序"`
`echo "2. 输入2 退出程序!"`
EOF
read -t 40 -p "请输入你所要执行程序对于的编号" num
case $num in
1)
fourOperator
;;
2)
echo "退出程序"
;;
*)
echo "你输入的数字不合法"
exit -1
esac
}
menu
[dayuanshuai@IDYS sh_day03]$ ./four_type_countv2.sh
*********************** 加减乘除运算程序开始 **********************
1. 输入1 进入加减乘除运算程序
2. 输入2 退出程序!
请输入你所要执行程序对于的编号1
请输入第一个数字12
请输入第二个数字45
请输入操作符+
运算结果为 57
[dayuanshuai@IDYS sh_day03]$ ./four_type_countv2.sh
*********************** 加减乘除运算程序开始 **********************
1. 输入1 进入加减乘除运算程序
2. 输入2 退出程序!
请输入你所要执行程序对于的编号1
请输入第一个数字006
请输入第二个数字045
请输入操作符*
运算结果为 270