SHELL内部参数
$# ----传递给程序的总的参数数目
$? ----上一个代码或者shell程序在shell中退出的情况,如果正常退出则返回0,反之为非0值。
$* ----传递给程序的所有参数组成的字符串。
$- ----在Shell启动或使用set命令时提供选项
$? ----上一条命令执行后返回的值
$$ ----当前shell的进程号
$! ----上一个子进程的进程号(若这空表示进程已结束)
$@ ----所有的参数,每个都用双括号括起
$n ----位置参数值,n表示位置
$0 ----当前shell名
-------------------------------------------------------------------------------------
SHELL 判断是否为数字 【转】
## 方法
2
, 可以,不过不是bash实现的,是使用了grep的正则
#
if
grep
'^[[:digit:]]*$'
<<<
"$1"
;then
# echo
"$1 is number."
#
else
# echo
'no.'
#fi
## 方法
3
#
if
[
"$1"
-gt
0
]
2
>/dev/
null
;then
# echo
"$1 is number."
#
else
# echo
'no.'
#fi
## 方法
4
,
case
#
case
"$1"
in
# [
1
-
9
][
0
-
9
]*)
# echo
"$1 is number."
# ;;
# *)
# ;;
#esac
## 方法
5
,awk
#echo $
1
| awk
'{print($0~/^[-]?([0-9])+[.]?([0-9])+$/)?"number":"string"}'
## 方法
5
,awk
#
if
[ -n
"$(echo $1| sed -n "
/^[
0
-
9
]\+$/p
")"
];then
# echo
"$1 is number."
#
else
# echo
'no.'
#fi
## 方法
6
,expr
expr $
1
"+"
10
&> /dev/
null
if
[ $? -eq
0
];then
echo
"$1 is number"
else
echo
"$1 not number"
fi
#####判断是否为汉字
#!/bin/bash
LC_ALL=C
[[ $1 != *[[:alnum:]]* && $1 != *[[:punct:]]* ]] && echo hanzi || echo string
------------------------------------------------------------------------------------
一些算术括展运算,如:
z=`expr $z + 2`等效于 z=$(($z + 2)) 等效于 z=$((z + 2 ))
递增 let n=n+1 等效于 (( n +=1))
> abc.txt 等效于 touch abc.txt
重定向
& > a.txt 将标准输出(屏幕)与错误输出重定向到a.txt
2>&1 stderr 重定向到stdout
&- 关闭输出
--------------------------------
匹配空格/去空格
sed 's/[[:space:]]*$//' <<< $content_answer
----------------------------------------
注意:写SHELL程序时,赋值前后不能有空格
---------------------------------------------------------
$! 运行在当前系统的最后一个PID(为空,表示进程已结束)
$$ 当前程序或脚本的PID
$@ 接受传来的所有参数(数组),如下:
[root@jet tmp]# cat f.sh
#!/bin/bash
echo "$@"
shift
echo "$@"
[root@jet tmp]# bash f.sh 1 2 3 4 5
1 2 3 4 5 <--打印所有参数
2 3 4 5 <--经过shift后,向前娜了一个参数位
$# 得到变量值长度(记录参数的个数,一般用来检查某脚本要求传进参数的个数),如下
[root@jet tmp]# cat f.sh
#!/bin/bash
stringZ="aafafkjflkaflhgkhglsg"
echo ${#stringZ}
echo `expr length $stringZ` <--可man expr 查看expr其它用法
数组
arr_string="a b c d e"
for i in ${arr_string[@]} <----${arr_string[@]} 实际是数组
do
echo $i
echo $arr_string[5] <-----打印指定元素
done
echo ${#arr_string[@]} <-----数组的元素的 个数 等于${#arr_string[*]} 输出 5 数组个数
echo ${arr_string[@]:0} 打印出数组的全部元素
echo ${arr_string[@]:1} 打印出数组的从第二个元素开始以后的全部元素 输出 b c d e
echo ${arr_string[@]:1:3} 打印出数组的从第二个到第四个元素 打印出 b c d
函数中传送数组并获取(数组参数)
function dis()
{
echo $@
}
str="how are you"
dis 123 $str
增加数组元素的个数
arr=( a b c d e f )
arr=("${arr[@]}" "g")
echo ${arr[@]} <-- 得到 a b c d e f g
[!a-zA-Z] 感叹号的意思为匹配 a-z 或A-Z
[^a-zA-Z] ^的意思是排除a-z ,A-Z
------------------------------------------------------
一些特殊字符
;
命令分隔符,可以用来在一行中来写多个命令.
--------------------------------------------
;;
终止"case"选项.
--------------------------------------------
:
什么也不做,常用来做死循环如
#!/bin/bash
while :
do
echo aaaa
done
: > a.txt 与 cat /dev/null > a.txt 效果相同,都会将文本内容清空,但:属于内建命令,
--------------------------------------------
** 幂运算 如 let "b=2**3"; echo $b
% 取模 expr 5 % 3
+= let "var += 5"; echo $var
-=
*=
/=
自加,自减一些写法
let "n = n + 1" 或 let "n++" 或 ((n++)) 或 :$((n++)) 或:$[ n++ ]
--------------------------------------------
浮点数比较
if [ $(echo "$mya <=4.00" |bc) = 1 ] ; then echo ok; f
------------------------------------------
~+ 相当于$PWD 变量
I/O重定向
cat {file1,file2,file3} > file4 将file1,file2,file3连接起来重定向到file4中
------------------------------------------------------------------------
从标准输入中得到数据
read -p "please enter the number :" num <-----num 为变量
read -s num <----不显示输入的字符
---------------------------------------------
#!/bin/bash
FILE=/etc/passwd
{
read line1
read line2
}< $FILE
echo $line1
echo $line2
-----------------------------------------------
command >&2 重定向 command 的 stdout 到 stderr
-----------------------------------------------
\<,\>
正则表达式中的单词边界.如:
bash$grep '\<the\>' textfile
----------------------------------------------
echo 后跟的一些参数
-n 在一行输出,不换行
----------------------------------------------
类似加法写法,小心
[jet@jet tmp]$ b=9
[jet@jet tmp]$ b+=5
[jet@jet tmp]$ echo $b
95
[jet@jet tmp]$ b=$b+5
[jet@jet tmp]$ echo $b
95+5
[jet@jet tmp]$ c=5
[jet@jet tmp]$ c=`expr $c + 5` <--- 这才是加法
[jet@jet tmp]$ echo $c
10
[jet@jet tmp]$ a=16+5
[jet@jet tmp]$ echo $a
16+5
[jet@jet tmp]$ let a=16+5 <---也可以用 let赋值
[jet@jet tmp]$ echo $a
21
[jet@jet tmp]$ let "b += 1" <---也可以用 let赋值
[jet@jet tmp]$ echo $b
2
-------------------------------------------------
$(command) 与`command` 相等,作用效果一样
-------------------------------------------------
Bash 变量是不分类型的
不像其他程序语言一样,Bash 并不对变量区分"类型".本质上,Bash 变量都是
.
但是依赖于上下文,Bash 也允许比较操作和算术操作.决定这些的关键因素就是,变量中的值
是否只有数字.
---------------------------------------------------
关于函数请求的变量
可用$1,$2.....$9 ,但是,当变量的个数大于9时应该这样表示${10}
#!/bin/bash
function c(){
echo v1 is "$1"
echo v2 is "$2"
echo v3 is "$3"
echo v4 is "$4"
echo v5 is "$5"
echo v6 is "$6"
echo v7 is "$7"
echo v8 is "$8"
echo v9 is "$9"
echo v10 is "${10}"
}
c 1 2 3 4 5 6 7 8 9 10 <--调用
-------------------------------------------------------
shift
shift 命令重新分配位置参数,其实就是向左移动一个位置.
$1 <--- $2, $2 <--- $3, $3 <--- $4, 等等.
老的$1 将消失,但是$0(脚本名)是不会改变的.如果你使用了大量的位置参数,那么
shift 命令允许你存取超过 10 个参数.虽然{}表示法也允许这样.
#!/bin/bash
until [ -z "$1" ]
do
echo "$1"
shift <---将参数向前移
done
exit
[jet@jet tmp]$ bash c.sh 1 2 3 4 5 6 7
1
2
3
4
5
6
7
----------------------------------------------------
转义
对于特定的转义符的特殊的含义
在 echo 和 sed 中所使用的
\n 意味着新的一行
\r 回车
\t tab 键
\v vertical tab(垂直 tab),查前边的 Ctl-K
\b backspace,查前边的 Ctl-H
\a "alert"(如 beep 或 flash)
\0xx 转换成 8 进制 ASCII 解码,等价于 oxx
------------------------------------------------------
test 命令用法
if [ -z "$1" ] 等价于 if test -z "$1"
-----------------------------------------------------
关于定义的是数组还是字符串区分
[root@jet script]# arr_string2="a b c d e" <--这是字符串
[root@jet script]# echo ${#arr_string2[@]}
1
[root@jet script]# arr_string=(a b c d e) 《---这才是数组,用括号的
[root@jet script]# echo ${#arr_string[@]} <--------数组长度
5
[root@jet script]# echo ${arr_string[@]:0} <-------- 所有数组的值
a b c d e
[root@jet script]# echo ${arr_string[@]:1} <--------从下标是1起到最后
b c d e
[root@jet script]# echo ${arr_string[@]:1:3} <--------从下标为1到3数组的值
b c d
----------------------
二元比较操作符,比较变量或者比较数字.注意数字与字符串的区别.
整数比较
-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" ]
< 小于(需要双括号),如:(("$a" < "$b"))
<= 小于等于(需要双括号),如:(("$a" <= "$b"))
> 大于(需要双括号),如:(("$a" > "$b"))
>= 大于等于(需要双括号),如:(("$a" >= "$b"))
bc计算
correct_rate=$(echo "scale=2;$Right/$have_done" | bc)
[root@jet script]# aaa=$(echo 'scale=2;(58.3+26.566)/35.4' | bc)
[root@jet script]# echo $aaa
2.39
[root@jet script]# bc <<< $(echo 'scale=2;(58.3+26.566)/35.4') <-----------另一种写法
2.39
字符串比较
= 等于,如:if [ "$a" = "$b" ]
== 等于,如:if [ "$a" == "$b" ],与=等价
注意:==的功能在[[]]和[]中的行为是不同的,如下:
[[ $a == z* ]] # 如果$a 以"z"开头(模式匹配)那么将为 true
[[ $a == "z*" ]] # 如果$a 等于 z*(字符匹配),那么结果为 true
[ "$a" == "z*" ] # 如果$a 等于 z*(字符匹配),那么结果为 true
一点解释,关于 File globbing 是一种关于文件的速记法,比如"*.c"就是,再如~也是.
但是 file globbing 并不是严格的正则表达式,虽然绝大多数情况下结构比较像.
如[ $a == z* ] # File globbing 和 word splitting 将会发生
!= 不等于,如:if [ "$a" != "$b" ]这个操作符将在[[]]结构中使用模式匹配.
> 小于(大于也是一样),在 ASCII 字母顺序下.如:
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ] 注意:在[]结构中"<"需要被转义.
逻辑操作(&& ||
写法如下:
if [ $condition1 ] && [ $condition2 ] 或 if [ $condition1 -a $condition2 ] 或 if [[ $condition1 && $condition2 ]]
注意; && || 不能出现在[...] 中
if [ $condition1 ] || [ $condition2 ] 或 if [ $condition1 -o $condition2 ] 或 if [[ $condition1 || $condition2 ]]
-------------------------------------------------------------------------------
sed 返回行号
sed "/查找内容/"q file.txt | sed -n '$='
--------------------------------------------------------------------
, 逗号操作符
逗号操作符可以连接 2 个或多个算术运算.所有的操作都会被执行,但是只有最后一个操作作为结果.
[jet@jet tmp]$ let "t1 = ((5 + 3 , 7 + 2, 45 - 5 ))"; echo $t1
40
let "t2 = ((a = 9, 15 / 3))" --->过程为: 把9賦值給a ,然后根据逗号操作符,把第最后一个值給t2
-------------------------------------------------------------------------------
将数组的值全部输出
echo ${PIPESTATUS[@]}
--------------------------------------------------------------------------
、获取数组元素的个数:
array=(bill chen bai hu) //一定要用括号
num=${#array[@]} //获取数组元素的个数。
-------------------------------------------------------------------------------
得到字符串长度
shell> a=ABC
shell> expr length ${a[@]}
获取字符串的长度:
str="hello"
len=${#str}
-------------------------------------------------------------------------------
几个内建PS参数
[jet@jet etc]$ echo $PS1
[\u@\h \W]\$
[jet@jet etc]$ echo $PS2
>
[jet@jet etc]$ echo $PS3
select 出来的提示符
[jet@jet etc]$ echo $PS4
+
---------------------------------------------------------------------------------
$PWD 与$OLDPWD
[jet@jet etc]$ echo $PWD
/etc
[jet@jet etc]$ cd ~
[jet@jet ~]$ echo $OLDPWD <---上次操作所在的路径位置
/etc
---------------------------------------------------------------------------------
关于子串及字符串截取
格式;${string:position}
${string:position:length}
[root@jet tmp]# cat f.sh
#!/bin/bash
stringZ="abcABC123defDEF456"
echo '${stringZ:0} is :' . ${stringZ:0}
echo '${stringZ:4} is :'. ${stringZ:4}
echo '${stringZ:5:3} is :'. ${stringZ:5:3}
echo '${stringZ: -4} is :'. ${stringZ: -4}
echo '${stringZ:(-4)} is :'. ${stringZ:(-4)}
[root@jet tmp]# bash f.sh
${stringZ:0} is : . abcABC123defDEF456 <-----此变量的所有串
${stringZ:4} is :. BC123defDEF456 <-----从正向索引为4开始截到最后(索引从0开始)
${stringZ:5:3} is :. C12 <-----从正向索引为5开始,向后截3位
${stringZ: -4} is :. F456 <-----反向截取4位(冒号和数字之间有空格)
${stringZ:(-4)} is :. F456 <-----反向截取4位(若不想用空格,可有括号)
expr substr $string $position $length
在 string 中从位置$position 开始提取$length 长度的子串.
[root@jet tmp]# a=abcABC123
[root@jet tmp]# expr substr $a 3 4
cABC <------------从第三位起截4个
[root@jet tmp]# expr match "$a": "\([abc]\)"
a <------------正则表达式截取
[root@jet tmp]# expr match "$a": "\(abc\)"
abc <------------ 正则表达式截取
[root@jet tmp]# expr match "$a": "\(aBc\)"
<------------正则表达式截取,因为不匹配,所以没有
[root@jet tmp]#
${string%substring}
从$string 的右边截掉第一个匹配的$substring
${string%%substring}
从$string 的右边截掉最后一个匹配的$substring
去除字符串后面的空格
sed 's/[[:space:]]*$//' <<< $string
子串削除
${string#substring} 从$string 的左边截掉第一个匹配的$substring
${string##substring} 从$string 的左边截掉最后一个匹配的$substring
${string%substring} 从$string 的右边截掉第一个匹配的$substring
${string%%substring} 从$string 的右边截掉最后一个匹配的$substring
例:批量修改文件后缀
[root@jet abc]# ls
a.txt b.txt c.txt d.txt e.txt f.txt g.txt
[root@jet abc]# cat f.sh
#!/bin/bash
filename=`ls /tmp/abc`
for i in $filename
do
myleft=${i%%.txt} <----截取后缀前面的部分
mv $i $myleft.TXT
done
批量修改文件名
#!/bin/bash
filename=`ls /tmp/abc`
for i in $filename
do
mv $i `echo "$i"_bak`
done
[root@jet abc]# ls
a.TXT b.TXT c.TXT d.TXT e.TXT f.TXT g.TXT
子串替换
子串替换
${string/substring/replacement} 使用$replacement 来替换第一个匹配的$substring.
${string//substring/replacement} 使用$replacement 来替换所有匹配的$substring.
${string/#substring/replacement} 如果$substring 匹配以$string 的开头部分,那么就用$replacement 来替换$substring.
${string/%substring/replacement} 如果$substring 匹配以$string 的结尾部分,那么就用$replacement 来替换$substring.
[root@jet abc]# mystring=abcABC123abcABC123abc
[root@jet abc]# echo ${mystring/abc/xyz}
xyzABC123abcABC123abc
[root@jet abc]# echo ${mystring//abc/xyz}
xyzABC123xyzABC123xyz
[root@jet abc]# echo ${mystring/#abc/xyz}
xyzABC123abcABC123abc
[root@jet abc]# echo ${mystring/%abc/xyz}
abcABC123abcABC123xyz
-----------------------------------------------------------------------------------
循环
while [ 条件为真时 ]
do
.....
done
-----------------
filename="/a.txt"
while read line <---line 为变量名,while read 每次读一行
do
.....
done < $filename
-----------------
until [ 条件为真时]
do
......
done
-----------------
case "变量" in
条件1)
command
;;
条件2)
command
;;
*) <----默认
command
;;
esac
---------------------
循环控制
break <---退出本层循环
break N <----退出循环,默认N=1,表示退出本层循环,若N=2表示退出此层的上次循环
continue <----结束本次循环,继续下次循环
continue N <---结束N层循环,继续外层循环,与break N类似,只是继续下次循环 ,比较难懂,尽量少用
#!/bin/bash
a="1 2 3 4 5 6"
b="11 22 33 44 55 66"
for i in ${a[@]}
do
for bb in ${b[@]}
do
if [ "$bb" -eq 33 ] ; then
continue <----结束本次循环,继续下次循环
elif [ "$i" -eq 5 ]; then
break 2 <--退出for循环
else
echo $bb
fi
done
echo $i
done
------------------------
here documnet如下:
cat << EOF > A.TXT <--将下面的内容写到A.txt中
> AFLAFA
> AF
> AF
> AF
> AF
> AF
>
> EOF
here string
command <<< $a <--$a 可理解为传递给command 要处理的内容,可同时传多个
------------------------------------------
局部变量的声明
在一个函数中,有时要用到局部变量,可用local来声明,如 local abc=555
-----------------------------------------------------------
得到一个在后台运行的进程可用 pidof 进程名 ,若没有找到此进程号,则说明此进程此时没有运行
--------------------------------------
read命令 -n(不换行) -p(提示语句) -n(字符个数) -t(等待时间) -s(不回显)
read -p "Enter your name:" name #name 为变量