认识bash这个shell
- 硬件,内核与shell
- shell是将命令转化成机器语言,由cpu执行。cpu执行结果又经过shell转换成我们能看懂的结果。shell看不到,摸不着,必须找一个软件连接到shell。linux终端(GUI)不是shell,它连接了人和shell。打开一个终端,终端会连接到shell(打开一个shell进程)。
- 系统中有那些shell呢?
cat /etc/shells #查看系统中有那些shell
结果 :
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/usr/bin/tmux
/usr/bin/screen#系统中有sh,bash等shell。
#linux默认用bash,命令行输入sh,则切换到sh shell。
- 为何要学习命令行界面的shell
1. 命令行操作快。远程桌面管理时,传输命令所占带宽小(相比传输图片)。
2. 命令行有大量快捷键,可以提高输入命令的速度。
- 系统的合法shell与/etc/shells功能
- bash shell的功能
- bash shell的内置命令:type
- 命令的执行
which ls #查找命令所在路径。 当路径为/bin..,/usr/bin,/sbin时说明此文件由其他软件包安装出来的,不是shell安装出来的。
which cd #命令结果会显示无此路径。cd是shell内置的命令(装shell才带的)。
type cd #结果:cd is a shell builtin。显示cd是shell内置的命令。
cal;date #同一行输入多个命令用分号隔开。显示日历和日期。
用 \ 换行,输入很长的命令。
shell变量的功能
- 什么是变量
~就是有个变量,就是用户的家目录。 - 变量的设置与显示:echo,unset
- 变量的功能
- 本地变量
变量名=变量值 #这是变量的定义方法(等号两边不要有空格,有空格要用双引号引起来)。变量的定义符合标识符的标准。
$变量名 #这是变量的使用方法。不加$,系统会把变量当做普通字符
xx=9
echo $xx #定义变量xx,输出结果。
unset xx #销毁变量xx。注意此时没有带$符号!!!!!!
本地变量:通过“变量名=变量值”定义的是本地变量。它只存在于当前shell。不会影响到子shell。
xx=9;#在当前shell定义变量xx
echo $$ #输出进程ID
bash #打开一个子shell
echo $$ #输出子shell的进程ID
echo $xx #在子shell中输出变量xx。结果为空。因为它不存在于子shell
exit #退出当前shell,回到定义xx的shell
echo $xx #结果为9.
- 环境变量
环境变量不但存在于当前shell,也会存在于子shell。
xx=10
export xx #把本地变量变成环境变量
export yy=10 #直接定义一个环境变量。
bash #打开一个子shell
echo $yy #在子shell中输出yy,结果为10
env # environment 显示所有环境变量
export #也是显示所有环境变量
declare -x xx=9 #定义一个环境变量
declare +x xx #将xx由环境变量变成本地变量
- 位置变量
写一个简单的脚本
vim ss.h #新建一个脚本文件
#!/bin/bash #此行是固定的。
echo "这个脚本的名字是:$0" #$0是脚本的名称。
echo "这个脚本的第一个参数是:$1"
echo "这个脚本的第二个参数是:$2"
echo "这个脚本的第三个参数是:$3"
echo "这个脚本的第四个参数是:$4"
echo "这个脚本共有$#个参数,分别是 $*"
$1,$2..分别是第一,第二..个参数。${13}:当位置不止一位时,用括号括起来。否则解析为$1,后面再附上3。$#是参数个数,$*表示所有参数。
chmod +x xx.sh #为文件加一个可执行权限。
./xx.sh a b c d #执行脚本。为脚本输入参数a,b,c,d;
bash xx.sh a b c d #功能同上
执行结果:
这个脚本的第一个参数是:a
这个脚本的第二个参数是:b
这个脚本的第三个参数是:c
这个脚本的第四个参数是:d
echo $PATH #写入一个命令时,通常要写入命令的路径。不写时,系统会到PATH这个变量中存储的路径去找。
echo $HOME #输出当前用户的家目录。
echo $USER #输出当前登录的用户,用户登录时赋值。
echo $HISTFILESIZE #输出系统最多用history缓存多少刚刚输入的命令。
zhangsan@ubuntu:~$ 这个命令输入提示符也是环境变量 PS1设定的。
PS2时换行符 >
- 影响显示结果的语系变量(locale)
locale -a #显示系统支持的所有编码
-
变量的有效范围
本地变量再当前shell有效。环境变量在当前shell和子shell有效。位置变量和脚本,环境都有关。 -
变量键盘读取,数组与生命:read,array,declare
- 在命令行用read
read xx #会提示输入
12343535 #此两行类似 xx=12343535
read
xxxx #默认给$REPLY赋值xxxx
- 在脚本中用read
#!/bin/bash
echo "请输入你的名字:"
read name
echo "欢迎您!$name!"
bash wel.sh #上述脚本名字wel.sh。运行脚本
结果:
请输入你的名字:
libai
欢迎您!libai!
3.array
数组功能强大。使用如下
xx=(aa bb cc)#定义一个名字叫xx,包含三个元素的数组。元素间用空格隔开。
echo ${xx[0]} #输出数组第一个元素。类似c数组。
echo ${xx[*]} #输出所有元素 * 可用 @ 代替
echo ${!xx[*]} #输出数组所有下标
echo ${#xx[*]} #输出数组长度
4.declare
declare -r aa #定义只读变量aa。赋值后不能再修改了。
readonly aa #同上一句
只读变量无法用unset命令销毁。
注意以下区别:
echo $yy #若yy没定义,则输出为空。yy不存在。
yy=
echo $yy #yy虽然没赋值,但yy却存在,知识值为空。
双引号,单引号和反引号
xx=10
echo $xx #输出10
echo "$xx" #输出10
echo '$xx' #单引号里的变量按字符串处理
推荐以下引用变量的方式
echo ${xx}#即把变量名用{}括起来。
例如
xx=book
echo "我买了10本$xxs" #结果:我买了10本。系统把xxs当成变量名,结果它不存在。
echo "我买了10本${xx}s" #结果:我买了10本books
echo "xxxxxxx `hostname` xxxx" #命令里面嵌套命令。用反引号。
- 与文件系统集及程序有关的限制关系:ulimit
ulimit -a #查看所有的大下限制。如文件大小,栈大小。
ulimit -f 2028 #限制文件大侠为2048k
- 变量内容的删除,替代和替换
r=${path##*sbin} - 别名
alias x=systmctl #给systemctl命令取别名x。类似宏
unlias x #取消别名systemctl
Besh Shell的操作环境
- 路径和命令查找顺序
不同路径下可能存有同名的命令。怎么知道是执行的那个路径下的命令?
type -a echo #查看echo命令的执行路径顺序
结果:
echo is a shell builtin #首先执行shell内置的命令。
echo is /bin/echo #上一个路径没有echo,则执行此路径的命令。
-
bash的登录和欢迎信息:/etc/issue,/etc/motd
/etc/issue 存放登录前的提示信息。
/etc/motd 存放登录后的提示信息。
可以修改。 -
bash的环境配置文件
已经在一个终端登录,在同一台机器再打开一个linux终端,就不要输入密码了。此状态的shell称为no-login shell。
打开终端,还没登录的状态,称为login-shell
登录时,login-shell会读入配置文件。这些配置文件包括:
/etc/profile #设置所有的全局环境(全局变量)。
/etc/inputrc #设置shell使用的快捷键
在用户家目录
.profile #显示当前用户的全局环境(全局变量)。
- 终端机的环境配置:stty,set
stty -a #显示系统所有快捷键
set -u #开启提示
echo $xx #若xx未定义,会有提示,
set -x#输出时,会连同输出使用的命令。在脚本的开始添加此语句,可以方便排错。
set +x #取消上述功能
- 通配符和特殊符号
ls [a-z][0-9]?[!0-9]*.mp3 #匹配"1个字母 1个数组 1个任意字符 非数字 任意长度串.mp3"文件。一个[]匹配一个字符。
数据流重定向
- 什么是数据流重定向
默认命令从键盘输入,结果输出到屏幕。可以进行修改。
输出重定向:
cal > xx #把日历输出到文件名未xx的文件中。若xx不存在,则系统会创建一个。若xx存在,则会覆盖xx内容。
cal >> xx #追加。注意>前面的命令一定要输入正确。
cal 2> xx #命令错误,重定向
cal 2>> xx #命令错误,追加
cal\ &> xx #无论命令输入正确与否,都导入。
输入重定向
tr 'a-z' 'A-Z' < filename #把filename内容中的小写字母转成大写字母,并输出。filename必须存在。
command < filename #把filename中的内容穿给前面的命令使用。
<< 符号的使用(here文档)
cat >xx <<endflag #把要看的内容导入到xx中。xx文件时从键盘输入的,输入结束标志是endflag
cat xx #再查看xx文件
aa=9
cat > xx <<end
${aa}
end #输入一个变量
cat xx #结果显示9.here文档支持变量
- 命令执行的判断依据:; && ||
系统中有一个容量为1的容器存放最近一次命令执行的结果。存放再&?
里面。命令正确执行,&?==0
,否则,&?为非零数
- 分号
一行输入多个命令。两个命令的执行互不影响。 - &&
command1 && command2 #只有两个命令都正确执行(都为0),结果才为真(0)。若命令1执行失败。则命令2不会执行。
- ||
command1 || command2 #只一个命令执行正确(一个为0),结果就为(0)。若命令1执行成功,则命令2不会执行。
管道命令(pipe)
command1 | command2 命令1的结果作为命令2的参数。
command1 | command2 |command3.... 可嵌套
如
ip addr | grep 'inet' #在ip addr命令的执行结果中挑选含inet的成分
- 选取命令:cut,grep
cut -d : -f 1 /etc/passwd#-d参数指明分割符。-f指明查看第几部分。最后是文件名。即以冒号为分隔符查看passwd中第1部分。这针对passwd这种格式规范的文件很有用。
last | cut -d ' ' -f 1 #last是先前用户登录信息。执行结果传给后面。通过空格分隔,输出第一部分。
grep keyword filename #在filename文件中查找含keyword关键字的部分。这是区分大小写。
grep -i keyword filename#忽略大小写
grep -in keyword filename #显示在原文件终端行号,忽略大小写。
grep -inv keyword filename #反向过滤。满足条件的过滤掉。
- 排序命令:sort,wc,uniq
command | sort #默认使用的是字典排序 653<68。按照字符排序。对命令结果排序(如cut)
command | sort -n #按数字大写排序(增序)
command | sort -n -r #按数字大写排序(减序)
sort -t : -k 3 /etc/passwd #-t指明分割符,-k指明第几部分。最后是文件名。
last|cut -d ' ' -f 1 | sort -u #-u使得重复的结果只显示一次
last|cut -d ' ' -f 1 | sort|uniq #同上
last|cut -d ' ' -f 1 | sort|uniq -c #会同时显示重复了多少次
wc filename #对filename文件进行统计。
wc -l filename#只显示有几行
wc -w filename#只显示有几个单词
wc -c filename#只显示有几个字符
wc a2
结果:
1 1 13 a2#1是有多少行。第二个1是单词数。13是字符数,每行有一个换行符。
ls -1 #一行一个显示文件
ls -1 |wc -l #显示当前目录有多少个文件
- 双向重定向:tee(保存中间结果)
ip addr |tee file |grep 'inet' #把中间结果保存在文件名为file文件中。会覆盖file原有内容
ip addr |tee -a file |grep 'inet' #把中间结果追加到文件名为file文件中
- 字符转换命令:tr,col,join,paste,expand
tr 'a-z' 'A-Z' <filename #并没有改变原文件filename
tr 'a-z' 'A-Z' <filename >filename #用法错误。会损害原文件。必须分成以下两步
tr 'a-z' 'A-Z' <filename >xxx
mv xx filename
cat filename1 > filename2 #把文件1直接写到文件2
cat passwd | tr -d ':' #删除passwd中的全部冒号。
command |cat -A #结果中的TAB键(^I)。
command |col -x #将结果中的tab键换成空格 col -x==expand
paste filename1 filename2 #把两个文件粘在一起显示出来。原文件不动。各放一列
join -t ': 'filename1 filename2#-t指明分隔符。有相同的才能合并。
- 切割命令:split
大文件分割成小文件。
split -b 10k filename xxx #将filename文件分割成10k大小的文件块。每块文件名字以xxx开头。
split -1 100 filename xxx #没100行分成一个文件。xxx是任意的。
cat xxx* > filename #将文件重新组合在一起
diff filename1 filename1 #比较两个文件。若一样输出空。
- 参数代换:xargs(常和find一起用)
find -name "file*"|ls -l #此命令的的执行结果是在当前目录浏览文件。(管道无效)
find -name "file*"|xargs ls -l#管道生效
- 关于减号 - 的用途