以下的例子都以bash为环境,别的shell可能不能用
-
基本知识
命令提示符,$表示普通用户,#表示管理员用户root ~/.bash_history 保存用户运行过的命令 ~/.bashrc 定义诸如提示文本、颜色等各类设置,启动shell时,会执行这组命令。登录shell则是~/.bash_profile 登录shell是登录主机后获得的那个shell。如果登录图形界面环境(比如 GNOME、KDE等)后打开了一个shell,就不是登录shell
-
终端打印
echo时,双引号中的!需要进行转义,但是单引号和直接跟在echo后面不用转义(比如 echo hello !) 使用不带引号的echo时,没法在所要显示的文本中使用分号 变量替换在单引号中无效 printf需要自己添加换行,可以跟格式,比如printf "%-5s %-10s %-4.2f\n" 1 Sarath 80.3456,横杠表示左对齐,不指定时采用右对齐 echo可以用-n来忽略结尾的换行,可以用-e和双引号来接收转义序列字符串,比如echo -e "1\t2\t3" 颜色有对应的编码,重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝 色=34,洋红=35,青色=36,白色=37,比如echo -e "\e[1;31m This is red text \e[0m",\e定义一个转义序列,[表示开始定义颜色,分号前为前景色,分号后为背景色,m表示颜色定义完毕 背景色的编码,重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47,比如echo -e "\e[1;42m Green Background \e[0m"
-
变量和环境变量
env查看终端的环境变量,cat /proc/$PID/environ来查看PID对应的进程的环境变量,比如cat /proc/2277/environ,测试发现无效 tr '\0' '\n'替换操作,将\0替换为\n,比如cat file | tr "abc" "xyz" > new_file var=value是赋值操作,var = value是相等操作,差别就是两个空格 echo "We have $count ${fruit}(s)" 引用变量$或者${}都可以 PATH通常定义在/etc/environment或/etc/profile或~/.bashrc 中,给PATH添加路径可以用export PATH="$PATH:/home/user/bin",export用于设置变量,冒号用于分隔 一些常用的环境变量HOME、PWD、USER、UID、SHELL 获取变量值的长度,length=${#var} root用户的UID是0 \u可以扩展为用户名,\h可以扩展为主机名,而\w可以扩展为当前工作目录,试了下好像不行,可能使用姿势不对
-
文件比较运算符
-e filename 如果 filename存在,则为真 [ -e /var/log/syslog ] -d filename 如果 filename为目录,则为真 [ -d /tmp/mydir ] -f filename 如果 filename为常规文件,则为真 [ -f /usr/bin/grep ] -L filename 如果 filename为符号链接,则为真 [ -L /usr/bin/grep ] -r filename 如果 filename可读,则为真 [ -r /var/log/syslog ] -w filename 如果 filename可写,则为真 [ -w /var/mytmp.txt ] -x filename 如果 filename可执行,则为真 [ -x /usr/bin/grep ] filename1 -nt filename2 如果 filename1比 filename2新,则为真 filename1 -ot filename2 如果 filename1比 filename2旧,则为真
-
数学运算
let命令可以直接执行基本的算术操作。当使用let时,变量名之前不需要再添加$ no1=4; no2=5; let result=no1+no2 # 直接这样result=no1+no2会打印no1+no2,而$result=no1+no2是个语法错误 echo $result 操作符[]的使用方法和let命令类似 result=$[ no1 + no2 ] 也可以使用$前缀 result=$[ $no1 + 5 ] 使用(())时,变量名之前需要加上$;expr同样可以用于基本算术操作 result=$(( no1 + 50 )) result=`expr 3 + 4` result=$(expr $no1 + 5) 以上这些方法只能用于整数运算,而不支持浮点数 可以用bc来执行一些浮点运算,单独使用会出现交互模式 echo "4 * 0.56" | bc no=54; echo "$no * 1.5" | bc 设置小数位数 echo "scale=4;3/8" | bc ibase用于设置输入数据的进制 obase用于输出的数据进制 echo "obase=2;100" | bc // 输出1100100 echo "ibase=2;100" | bc // 输出4 平方和平方根 echo "sqrt(100)" | bc echo "10^10" | bc
-
文件描述符
0 stdin(标准输入) 1 stdout(标准输出) 2 stderr(标准错误) 以上都有对应的设备文件,/dev/stdin、/dev/stdout、/dev/stderr 最常见的文件输入方式 输入时会先清空文件内容 echo "This is a sample text 1" > temp.txt 追加内容 echo "This is sample text 2" >> temp.txt 当一个命令发生错误并退回时,会返回一个非0的退出状态;当命令成功完成后,会返回数字0。退出状态可以从特殊变量$?中获得(在命令执行之后立刻运行echo $? 就可以打印出退出状态 将标准输入输出重定向 cmd 2>stderr.txt 1>stdout.txt 将stderr转换成stdout,stderr和stdout都被重定向到同一个文件中 cmd 2>&1 output.txt 同上 cmd &> output.txt 只看看命令是否执行正确而不想看任何输出(把标准输入指向了/dev/null) cat $filename >/dev/null /dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF 删除文件内容而不删除文件本身 cat /dev/null > /var/log/messages 有同样的效果,但不会产生新的进程 : > /var/log/messages tee命令用于读取标准输入的数据,并将其内容输出成文件,默认情况下,tee命令会将文件覆盖,-a选项,用于追加内容。tee不读取stderr的内容 command | tee FILE1 FILE2 重定向操作符(>、>>),使用特定的文件描述符,必须将描述符编号置于操作符之前 >等同于1> >>等同于1>> 打开交互模式,读取输入,直到输入EOF,停止,然后加入到test.sh cat << EOF > test.sh cat << EOF >> test.sh 读取test1.sh文件的内容,并追加到testShell cat < test1.sh >> testShell 不要玩这个,会死循环(?) cat < testShell >> testShell 自定义文件描述符 创建读取 exec 3<testShell 读取,只能读取一次 cat<&3 创建写入 exec 4>output.txt 写入,可以多次执行,而且后面内容会追加 echo newline >&4 创建追加 exec 5>>input.txt 追加,可以多次执行,后面内容会追加 echo appended line >&5
-
数组和关联数组
假设array_var是一个数组,打印array_var的值 echo ${array_var[*]} 或 echo ${array_var[@]} 打印某个索引对应的值 echo ${array_var[0]} index=5 echo ${array_var[$index]} 打印长度 echo ${#array_var[*]} 关联数组 先声明 declare -A fruits_value 赋值 fruits_value=([index1]=val1 [index2]=val2) 或 fruits_value[index1]=val1 fruits_value[index2]=val2 打印索引 echo ${!fruits_value[*]} 或 echo ${!fruits_value[@]}
-
别名
alias install='sudo apt-get install' 写入bashrc echo 'alias cmd="command seq"' >> ~/.bashrc 取消别名 unalias 或 alias example= #等号后面啥都没有 删除前备份文件 alias rm='cp $@ ~/backup && rm $@' $@ 表示全部参数 $# 表示参数长度 忽略别名,\command,比如\cp,可以防止攻击或者误用
-
获取终端信息
获取终端的行数和列数 tput cols tput lines 打印出当前终端名 tput longname 将光标移动到坐标(100,100)处 tput cup 100 100 设置终端背景色 tput setb n 其中n可以在0到7之间取值 设置文本前景色 tput setf n 其中n可以在0到7之间取值 设置文本样式为粗体 tput bold 设置下划线的起止 tput smul tput rmul 删除从当前光标位置到行尾的所有内容 tput ed #!/bin/sh #Filename: password.sh echo -e "Enter password: " stty -echo read password stty echo echo echo Password stty选项-echo禁止将输出发送到终端,选项echo允许发送输出 read 命令被用来从标准输入读取单行数据。这个命令可以用来读取键盘输入,当使用重定向的时候,可以读取文件中的一行数据
-
日期和延时
读取日期 date UTC时间,单位:秒 date +%s 格式转换 date --date "Thu Nov 18 08:07:21 IST 2010" +%s 获取星期几 date --date "Jan 20 2001" +%A 查看命令statements所花的时间 start=$(date +%s) statements; end=$(date +%s) difference=$(( end - start)) echo Time taken to execute commands is $difference seconds. 循环输出1到5 #!/bin/bash echo -n Count: tput sc #存储光标位置 count=0; while true; do if [ $count -lt 5 ]; then let count++; sleep 1; tput rc #恢复光标位置 tput ed #清除从当前光标位置到行尾之间的所有内容 echo -n $count; else exit 0; fi done
-
调试
打印当前在执行的命令 bash -x script.sh 打印出位于-x和+x之间的代码 for i in {1..6}; do set -x echo $i set +x done echo "Script executed"
-
函数
fname() { echo $1, $2; #访问参数1和参数2,$0代表当前脚本的文件名 echo "$@"; #以列表的方式一次性打印所有参数 echo "$*"; #类似于$@,但是参数被作为单个实体 return 0; #返回值 } 函数导出 export -f fname 获取函数或者命令的返回值,$? cmd; echo $?;
-
将命令的输出读入变量
子shell cmd_output=$(ls | cat -n) echo $cmd_output 反引用 cmd_output=`ls | cat -n` echo $cmd_output 用()生成子shell,子shell执行不影响当前shell pwd; (cd /bin; ls); pwd; 使用子shell或反引用的方法将命令的输出读入一个变量中,可以将它放入双引号中,以保留空格和换行符 如果text.txt是一个包含空格和换行的文本,这种方式会丢失内容 out=$(cat text.txt) echo $out 这种就不会 out="$(cat tex.txt)" echo $out
-
不使用回车读取 n个字符
把输入截取2个字符,并保存到变量var里,输入的时候就会被截断 read -n 2 var 无回显输入 read -s var 限制输入的时间,单位秒 read -t timeout var 设置结束标记为冒号 read -d ":" var
-
运行命令直至成功
在大多数现代系统中,true是作为/bin中的一个二进制文件来实现的,每执行一 次while循环,shell就生成一个进程 repeat() { while true do $@ && return done } 冒号总是返回为0的退出码,和true的效果一样,并且不会生成多个进程 repeat() { while :; do $@ && return; done } 重复执行期间延时30s repeat() { while :; do $@ && return; sleep 30; done }
-
字段分隔符和迭代器
IFS内部字段分隔符 data="name,sex,rollno,location" oldIFS=$IFS IFS=, for item in $data; do echo Item: $item done IFS=$oldIFS 循环的写法 for var in list do commands; 使用变量$var done 另一种 for((i=0;i<10;i++)) { commands; #使用变量$i } while循环 while condition do commands; done until循环 x=0; until [ $x -eq 9 ]; #条件是[$x -eq 9 ] do let x++; echo $x; done 生成1到50的一种简单写法 {1..50}
-
比较与测试
if condition; then commands; else if condition; then commands; else commands; fi [ condition ] && action; # 如果condition为真,则执行action [ condition ] || action; # 如果condition为假,则执行action [ $var1 -ne 0 -a $var2 -gt 2 ] #使用逻辑与-a,这里不能用&&和||,&&和||用于将多个条件组合起来 [ $var1 -ne 0 -o var2 -gt 2 ] #逻辑或 -o 检查字符串要用两个中括号 [[ $str1 = $str2 ]] [[ $str1 != $str2 ]] [[ -z $str1 ]]:如果str1包含的是空字符串,则返回真 [[ -n $str1 ]]:如果str1包含的是非空字符串,则返回真 test命令 if [ $var -eq 0 ]; then echo "True"; fi 可以写成: if test $var -eq 0 ; then echo "True"; fi
这还只是第一章,内容有点多。。。