shell 积累

 
fg  把一个后台运行的作业提到前台来。
sleep 100&
fg
disown 删除当前作业列表中的作业
sleep 100& --->  [1] 534
jobs ------> [1]+ running sleep 100&
disown 
jobs ------>  
 
eval 将表达式中的参数,或者表达式列表,组合起来,并且评估它们.包含在表达式中的任何变量
都将被扩展.结果将会被转化到命令中.这对于从命令行或者脚本中产生代码是很有用的.
34 for i in ls df; do
35 value=eval $i
36 # value=$i has an entirely different effect here.
36 # "eval" 将会评估命令 "ls" 和 "df" . . .
38 # 术语 "ls" 和 "df" 就具有特殊含义,
39 #+ 因为它们被解释成命令,
40 #+ 而不是字符串本身.
41 echo $value
42 done
 
逻辑与
1 if [ $condition1 ] && [ $condition2 ]
2 # 与: if [ $condition1 -a $condition2 ] 相同
3 # 如果condition1和condition2都为true,那结果就为true.
5 if [[ $condition1 && $condition2 ]] # 也可以.
6 # 注意&&不允许出现在[ ... ]中.
|| 逻辑或
1 if [ $condition1 ] || [ $condition2 ]
2 # 与: if [ $condition1 -o $condition2 ] 相同
3 # 如果condition1或condition2为true,那结果就为true.
4 
5 if [[ $condition1 || $condition2 ]] # 也可以
6 # 注意||不允许出现在[ ... ]中.
 
如果想在bash中执行浮点运算,用bc工具或调用数学库函数,还有就是调用awk
幂运算 ** 
let "x=5**3" ;echo "x=$x"  =====>x=125
常用test命令
文件:
-f file是一个普通文件
-e file存在
-d 文件是个目录
-b 文件是个块设备
-O 你是文件的所有者
-r file 具有read 权限(对于当前用户)
-w  file 具有write 权限(对于当前用户)
f1 -nt f2 file f1 is newer than f2
f1 -ot f2 f1 is older than f2

对于整数的test

-eq 等于,如:if [ "$a" -eq "$b" ]

-ne 不等于,如:if [ "$a" -ne "$b" ]
-gt 大于,如:if [ "$a" -gt "$b" ]
-ge 大于等于,如:if [ "$a" -ge "$b" ]
-lt 小于,如:if [ "$a" -lt "$b" ]
-le 小于等于,如:if [ "$a" -le "$b" ]
 
zcat 用来查看.gz结尾的压缩文件 
filename=$1
if [ ${filename##*.} != "gz" ]
# 在变量替换中使用中括号
then
echo "File $1 is not a gzipped file!"
${string#substring}
 从$string的左边截掉第一个匹配的$substring
${string##substring}
 从$string的左边截掉至最后一个匹配的$substring
1 stringZ=abcABC123ABCabc4 
5 echo ${stringZ#a*C} # 123ABCabc
6 # 截掉'a'和'C'之间最近的匹配.
7 
8 echo ${stringZ##a*C} # abc
9 # 截掉'a'和'C'之间最远的匹配. 
${string%substring}
 从$string的右边截掉第一个匹配的$substring
${string%%substring}
 从$string的右边截掉最后一个匹配的$substring
1 stringZ=abcABC123ABCabc
4 
5 echo ${stringZ%b*c} # abcABC123ABCa
6 # 从$stringZ的后边开始截掉'b'和'c'之间的最近的匹配
7 
8 echo ${stringZ%%b*c} # a
9 # 从$stringZ的后边开始截掉'b'和'c'之间的最远的匹配
${string/substring/replacement}
使用$replacement来替换第一个匹配的$substring.
${string//substring/replacement}
使用$replacement来替换所有匹配的$substring.
1 stringZ=abcABC123ABCabc
2 
3 echo ${stringZ/abc/xyz} # xyzABC123ABCabc
4 # 用'xyz'来替换第一个匹配的'abc'.
5 
6 echo ${stringZ//abc/xyz} # xyzABC123ABCxyz
7 # 用'xyz'来替换所有匹配的'abc'.
< 小于(需要双括号),如:(("$a" < "$b"))
<= 小于等于(需要双括号),如:(("$a" <= "$b"))
> 大于(需要双括号),如:(("$a" > "$b"))
>= 大于等于(需要双括号),如:(("$a" >= "$b"))
字符串的test
=  等于 if [ "$a" = "$b" ]
== 等于,如:if [ "$a" == "$b" ],与=等价
注意:==的功能在[[]]和[]中的行为是不同的,如下:
1 [[ $a == z* ]] # 如果$a以"z"开头(模式匹配)那么将为true
2 [[ $a == "z*" ]] # 如果$a等于z*(字符匹配),那么结果为true
3 
4 [ $a == z* ] # File globbing 和word splitting将会发生
5 [ "$a" == "z*" ] # 如果$a等于z*(字符匹配),那么结果为true
一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是.
!= 不等于,如:if [ "$a" != "$b" ]
< 小于,在ASCII字母顺序下.如:
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
注意:在[]结构中"<"需要被转义.
> 大于,在ASCII字母顺序下.如:
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
注意:在[]结构中">"需要被转义.
-z 字符串为"null".就是长度为0.
 
(()) 用来计算一个算术表达式的结果。如果结果为0,就返回“false” 或1 ,如果计算结果非0 ,则返回“true” 或者 0
 
当一个脚本以不带参数exit来结束时,脚本的退出状态就由脚本中最后执行命令来决定.
echo -e "x\ty" ===> x  y  enable the backslash escaplator. 
echo  "x\ty"=========> x\ty
echo "\"hello\",he said" ===> "hello",he said      (use \ to show the double quotes ")
echo "\$variable" ====> $variable    not enable the "$" symbol
echo $(ls -l)  结果将不换行。
echo "$(ls -l)" 结果换行
$RANDOM 产生0-32767之间的一个伪随机整数。 若想产生在某个区间里的整数,用取模操作(%)
产生在100以内的的整数
RANGE=100
 
number = $RANDOM 
let "number %= $RANGE"
另外一种方法 
 # 在6到30之间产生随机数.
    rnumber=$((RANDOM%25+6))
 
 
$#命令行参数的个数
$* 所有命令行的参数
$_ 命令行最后的参数
$$ 当前进程的PID
 
seq 10 1 2 3 4 5 6 7 8 9 10
seq 5 10 5 6 7 8 9 10 从5开始到10结束
seq 4 2 10 4 6 8 10 从4开始,到10结束,间隔为2
exit nnn命令将会把nnn退出码传递给shell(nnn必须是10进制数 0-255)
当一个脚本以不带参数exit来结束时,脚本的退出状态就由脚本中最后执行命令来决定.
1 #!/bin/bash 2 # int-or-string.sh: 整形还是string? 3 4 a=2334 # 整型 5 let "a += 1" 6 echo "a = $a " # a = 2335 7 echo # 还是整型 8 9 10 b=${a/23/BB} # 将23替换成BB 11 # 这将把b变量从整型变为string 12 echo "b = $b" # b = BB35 13 declare -i b # 即使使用declare命令也不会对此有任何帮助,9.4节有解释 14 echo "b = $b" # b = BB35
15 16 let "b += 1" # BB35 + 1 = 17 echo "b = $b" # b = 1 18 echo 19 20 c=BB34 21 echo "c = $c" # c = BB34 22 d=${c/BB/23} # S将BB替换成23 23 # 这使得$d变为一个整形 24 echo "d = $d" # d = 2334 25 let "d += 1" # 2334 + 1 = 26 echo "d = $d" # d = 2335 27 echo
 
 wait
停止脚本的运行,直到后台运行的所有作业都结束为止,或者直到指定作业号或进程号为选
项的作业结束为止.
你可以使用wait命令来防止在后台作业没完成(这会产生一个孤儿进程)之前退出脚本.
1 #!/bin/bash
 2 
 3 ROOT_UID=0 # 只有$UID 为0的用户才拥有root权限.
 4 E_NOTROOT=65
 5 E_NOPARAMS=66
 6 
 7 if [ "$UID" -ne "$ROOT_UID" ]
 8 then
 9 echo "Must be root to run this script."
10 # "Run along kid, it's past your bedtime."
11 exit $E_NOTROOT
12 fi  
13 
14 if [ -z "$1" ]
15 then
16 echo "Usage: `basename $0` find-string"
17 exit $E_NOPARAMS
18 fi
19 
20 
21 echo "Updating 'locate' database..."
22 echo "This may take a while."
23 updatedb /usr & # 必须使用root身份来运行.
24 
25 wait
26 # 将不会继续向下运行,除非 'updatedb'命令执行完成.
27 # 你希望在查找文件名之前更新database.
28 
29 locate $1
30 exit 0
jobs  列出后台所有正在运行的作业。给出作业号
sleep 100&
jobs
exec
这个shell内建命令将使用一个特定的命令来取代当前进程.一般的当shell遇到一个命令,
它会fork off一个子进程来真正的运行命令.使用exec内建命令,shell就不会fork了,并
且命令的执行将会替换掉当前shell.因此,当我们在脚本中使用它时,当命令实行完毕,
它就会强制退出脚本
注意: find命令的 -exec选项与shell内建的exec命令是不同的.
unset 将取消变量赋值
set -- 取消参数传递给shell脚本
 1 #!/bin/bash
 2 # unset.sh: Unset一个变量.
 3 
 4 variable=hello # 初始化.
 5 echo "variable = $variable"
 6 
 7 unset variable # Unset.
 8 # 与 variable= 的效果相同
 
将脚本内的参数传递给文件,用set,可以有2种用法
set `uname -a` ; echo $1 $2             $1= linux      $2= localhost.localdomain  即shell脚本的第一个参数为linux, 第二个为localhost.localdomain
variable="one two three four five"; set -- $variable; 则set将 one two three ... 分别传递给文件的第一个参数,第二个,第三个。。。
取消参数传递 用set --
shift命令是将右面的参数向左移动一个单位。 即相当于删除一个参数 ;想移动几个参数,就用多少个shift
example_set:
 1 #!/bin/bash
 2 
 3 variable="one two three four five"
 4 
 5 set -- $variable
 6 # 将位置参数的内容设为变量"$variable"的内容.
 7 
 8 first_param=$1
 9 second_param=$2
10 shift; shift # Shift past first two positional params.
11 remaining_params="$*"
12 
13 echo
14 echo "first parameter = $first_param" # one
15 echo "second parameter = $second_param" # two
16 echo "remaining parameters = $remaining_params" # three four five
18 echo; echo
19 
20 # 再来一次.
21 set -- $variable
22 first_param=$1
23 second_param=$2
24 echo "first parameter = $first_param" # one
25 echo "second parameter = $second_param" # two
26 
27 # ==================================================
28 
29 set --
30 # Unsets positional parameters if no variable specified.
30 # 如果没指定变量,那么将会unset所有的位置参数.
31 
32 first_param=$1
33 second_param=$2
34 echo "first parameter = $first_param" # (null value)
35 echo "second parameter = $second_param" # (null value)
36 
37 exit 0
set命令用来修改内部脚本变量的值.一个作用就是触发选项标志位来帮助决定脚本的行
为.另一个应用就是以一个命令的结果(set `command`)来重新设置脚本的位置参数.脚本
将会从命令的输出中重新分析出位置参数.
example_set:
 1 #!/bin/bash
 2 
 3 # script "set-test"
 4 
 5 # 使用3个命令行参数来调用这个脚本,
 6 # 比如, "./set-test one two three".
 7 
 8 echo
 9 echo "Positional parameters before set \`uname -a\` :" #uname命令打印操作系统名
10 echo "Command-line argument #1 = $1"
11 echo "Command-line argument #2 = $2"
12 echo "Command-line argument #3 = $3"
13 
14 
15 set `uname -a` # 把`uname -a`的命令输出设置
16 # 为新的位置参数.
17 
18 echo $_ # 这要看你的unmae -a输出了,这句打印出的就是输出的最后一个单词.
19 # 在脚本中设置标志.
20 21 echo "Positional parameters after set \`uname -a\` :"
22 # $1, $2, $3, 等等. 这些位置参数将被重新初始化为`uname -a`的结果
23 echo "Field #1 of 'uname -a' = $1"
24 echo "Field #2 of 'uname -a' = $2"
25 echo "Field #3 of 'uname -a' = $3"
26 echo ---
27 echo $_ # ---
28 echo
29 
30 exit 0
################################End Script########################################
 
 when we have done a shell program. we can put it in the /usr/local/bin/ directory.
then we can use it at anytime at anywhere in the system.
PS3="Choose (1-5):"
echo "Choose from the list below."
select name in red green blue yellow magenta
do
	break
done
echo "You chose $name."
 
secretNumber=$(( ((`date +%N` / 1000) % 100) +1 ))
guess=-1
while [ "$guess" != "$secretNumber" ]; do
	echo -n "I am thinking of a number between 1 and 100. Enter your guess:"
	read guess
	if [ "$guess" = "" ]; then
		echo "Please enter a number."
	elif [ "$guess" = "$secretNumber" ]; then
		echo -e "\aYes! $guess is the correct answer!"
	elif [ "$secretNumber" -gt "$guess" ]; then
		echo "The secret number is larger than your guess. Try again."
	else
		echo "The secret number is smaller than your guess. Try again."
	fi
done

echo -n do not output the trailing newline

 

  • If you write "test && command", the command will only be executed if the test succeeds .
  • If you write "test || command", the command will only be executed if the test fails .

Run these tests: $ true && echo "Yes."
Yes.
$ false || echo "Yes."
Yes.

 

shell也有一个真正的调试模式,如果脚本"strangescript"出错,可以使用如下命令进行调试:
sh -x strangescript 
shell还有一个不执行脚本只检查语法的模式,命令如下:
sh -n your_script




#!/bin/bash
 x=1999
 let "x = $x + 1"
整数运算一般通过let和expr命令来实现,对变量可以写: let "x=$x+1" 或 x=expr $x+1
整数操作 字符操作
相同 -eq =
  不同 -ne !=
  大于 -gt >
  小于 -lt <
 大于或等于 -ge
 小于或等于 -le
字符为空 -z
字符不为空 -n

比较字符串 a 和 b 是否相等就写作:if [ $a = $b ]

  判断字符串 a 是否为空就写作: if [ -z $a ]

  判断整数变量 a 是否大于 b 就写作:if [ $a -gt $b ]

bash对文件的操作
if [ -x /root ] 可以用于判断 /root 目录是否可以被当前用户进入。

  运算符 含义( 满足下面要求时返回 TRUE )
  -e file 文件 file 已经存在
  -f file 文件 file 是普通文件
  -s file 文件 file 大小不为零
  -d file 文件 file 是一个目录
  -r file 文件 file 对当前用户可以读取
  -w file 文件 file 对当前用户可以写入
  -x file 文件 file 对当前用户可以执行
  -g file 文件 file 的 GID 标志被设置
  -u file 文件 file 的 UID 标志被设置
  -O file 文件 file 是属于当前用户的
  -G file 文件 file 的组 ID 和当前用户相同
  file1 -nt file2 文件 file1 比 file2 更新
  file1 -ot file2 文件 file1 比 file2 更老

[ -f "$file" ] 判断$file是否是一个文件
[ $a -lt 3 ] 判断$a的值是否小于3,同样-gt和-le分别表示大于或小于等于
[ -x "$file" ] 判断$file是否存在且有可执行权限,同样-r测试文件可读性
[ -n "$a" ] 判断变量$a是否有值,测试空串用-z
[ "$a" = "$b" ] 判断$a和$b的取值是否相等
[ cond1 -a cond2 ] 判断cond1和cond2是否同时成立,-o表示cond1和cond2有一成立
要注意条件测试部分中的空格。在方括号的两侧都有空格,在-f、-lt、=等符号两侧同样也有空格。如果没有这些空格,Shell解释脚本的时候就会出错。

$*表示整个参数列表,不包括$0,也就是说不包括文件名的参数列表。

制作帮助文档
----------------------------
cat << HELP



HELP
exit 0
---------------------------
将上面的帮助文档做成一个help函数。
[ -z "$1" ] && help 第一个参数为空则显示help函数
[ "$1" = "-h" ] && help 第一个参数为-h则显示help函数


if 循环语句
#!/bin/bash
#test the usege of bash control file

if [ -x /home/collins ]
then
echo "I have entered in collins directory"
if [ -e /home/collins/log ]
then
echo "helloworld file exits"
fi
fi
注意 if 语句与【之间一定要有空格 后面 】的前面也要有空格。
如果将 if 和 then写在一行里面,就必须在 then 前面加上分号,如:if [ expression ]; then

for 循环语句
#!/bin/bash
  for day in 1 2 3 4 5 6
  do
  echo $day
  done

如果列表被包含在一对双引号中,则被认为是一个元素 "1 2 3 4 5 6" 则结果为 1 2 3 4 5 6

case 语句
#!/bin/bash
  echo "Hit a key, then hit return."
  read Keypress
  case "$Keypress" in
  [a-z] ) echo "Lowercase letter";;
  [A-Z] ) echo "Uppercase letter";;
  [0-9] ) echo "Digit";;
  * ) echo "Punctuation, whitespace, or other";;
  esac
  exit 0

break 语句可以让程序流程从当前循环体中完全跳出,而 continue 语句可以跳过当次循环的剩余部分并直接进入下一次循环。


局部变量
若想定义一个局部变量,则可以在赋初值时在变量前加上一个local关键字。
#!/bin/bash
 HELLO=Hello
 function hello { //注意hello 后面一定要留个空格,及函数名称和函数体之间要有空格。
 local HELLO=World
 echo $HELLO
  }
 echo $HELLO
 hello

BASH 中的变量与 C 语言中变量的区别
  这里我们为原来不熟悉 BASH 编程,但是非常熟悉 C 语言的程序员总结一下在 BASH 环境中使用变量需要注意的问题。
  1,BASH 中的变量在引用时都需要在变量前加上 "$" 符号( 第一次赋值及在For循环的头部不用加 "$"符号 );
  2,BASH 中没有浮点运算,因此也就没有浮点类型的变量可用;
  3,BASH 中的整形变量的比较符号与 C 语言中完全不同,而且整形变量的算术运算也需要经过 let 或 expr 语句来处理;
输入,输出和错误输出
标准输入(stdin) 标准输出(stdout) 标准错误输出(stderr) 一般将标准输出表示为1,错误输出表示为2,

如果直接执行 find /home -name lost* > all_result ,其结果是只有标准输出被存入 all_result 文件中

$ find /home -name lost* > all_result 2>& 1

上面这个例子中将首先将标准错误输出也重定向到标准输出中,再将标准输出重定向到 all_result 这个文件中。这样我们就可以将所有的输出都存储到文件中了。



函数的返回值在调用该函数的程序体中通过 $? 保留字来获得。
BASH 的返回值可以用return语句来指定返回一个特定的整数,如果没有 return 语句显式的返回一个返回值,则返回值就是该函数最后一条语句执行的结果(一般为 0,如果执行失败返回错误码)

select 语句可以让用户从一组数据中进行选择。
#!/bin/bash
echo "Your choice?"
select var in "a" "b" "c"; do
break
done
echo "Your choice is $var"
-------------------------------------------
运行结果是
Your choice?
1) a
2) b
3) c
输入2 然后显示 Your choice is b

bash也提供了真正的调试方法,在执行程序时加上 ?x 参数。
sh ?x filename.sh


-----------------------------------------
一个脚本
#!/bin/sh
# vim: set sw=4 ts=4 et:

ver="0.1"
help()
{
cat << HELP
rotatefile -- rotate the file name
USAGE: rotatefile [-h] filename
OPTIONS: -h help text
EXAMPLE: rotatefile out

This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1[BR]
and create an empty out-file

The max number is 10

version $ver
HELP

exit 0
}

error()
{
echo "$1"
exit 1
}

while [ -n "$1" ]; do
case $1 in
-h) help;shift 1;;
--) break;;
-*) echo "error: no such option $1. -h for help";exit 1;;
*) break;;
esac
done

# input check:
if [ -z "$1" ] ; then
error "ERROR: you must specify a file, use -h for help"
fi

filen="$1"
# rename any .1 , .2 etc file:
for n in 9 8 7 6 5 4 3 2 1; do
if [ -f "$filen.$n" ]; then
p=`expr $n + 1`
echo "mv $filen.$n $filen.$p"
mv $filen.$n $filen.$p
fi
done

# rename the original file:
if [ -f "$filen" ]; then
echo "mv $filen $filen.1"
mv $filen $filen.1
fi

echo touch $filen
touch $filen

你可能感兴趣的:(shell)