脚本的参数
参数变量
$* |
传递给脚本/函数的所有参数(把所有参数当成一个字符串) |
[email protected] |
参数名字 |
$0 |
文件名字(first.sh…) |
$# |
总共有多少个参数 |
$$ |
脚本的 PID |
$! |
上一个被执行的命令的 PID(后台运行的进程) |
IFS=, # 将函数参数的分隔符改成用‘,‘ 例如 IFS=:
var=test
echo ${#var}
4
echo $#var
0var
echo $# == 0
# 2014-10-16 16:21:41
## 测试 $* 和 $# 的区别
function countargs {
echo $# args;
}
countargs "$*"
countargs "[email protected]"
## 将上面的代码保存为一个文件, sh FILENAME a b c
## 3 args
## 1 args
使用默认参数
${varname:-word} |
如果 varname 为 null,返回 word, (${count:-0}) |
${varname:+word} |
如果 varname 为 null,返回 null,否则返回 word,测试一个变量的存在性.${count:+1}返回 1,即‘true‘ |
${varname:=word} |
如果 varname 为 null,将其设置为 word, 不能设置位置参数和特殊参数 |
${varname:?message} |
如果 varname 为 null,打印 varname:后跟信息 message,并退出当前命令或脚本,捕获为定义变量导致的错误 |
${varname:NUM |
返回从 NUM 开始的字符串, 开头以 0 计算 |
${varname:NUM:LENG |
返回从 NUM 开始的 LENG 长度字符串 |
count=frogfotman
${count:4} 返回 footman
${count:4:4} 返回 foot
sort -nr $1 | head -${2:-10} # the first version
# 当后面没有接文件的时候, 会有一些奇怪的信息
filename=${1:?"filename missing"}
howmany=${2:-10}
sort -nr $filename | head -$howmany # the second version
# 当后面没有接文件的时候, 输出的错误信息有点不尽人意
filename=$1
filename=${filename:?"filename missing."}
howmany=${2:-10}
sort -nr $filename | head -$howmany # the third version
filename=$1
filename=${filename:?"filename missing."}
howmany=${2:=1}
sort -nr $filename | head -$howmany # the fourth version
# 会把 1 赋值给 $2, shell 会提示出错, "cannot assign in this way"
filename=$1
filename=${filename:?"filename missing"}
howmany=$2
sort -nr $filename | head -${howmany:=10} # the fifth version
filename=$1
filename=${filename:?"filename missing"}
howmany=$3
header=$2
echo -e -n ${header:+"ablums artist\n"}
# 如果变量为空什么都不输出, 连空行也不输出, 如果不为空就输出
# echo $head # 的值不是后面的字符串...注意区分,他只是返回
sort -nr $filename | head -${howmany:=3}
getopts
while getopts ":ab:c" opt; do
case $opt in
a) echo ‘this is a‘ ;;
b) echo ‘this is b‘
echo "args b is $OPTARG" ;;
c) echo ‘this is c‘ ;;
\?) echo ‘usage: alice [-a][-b bargs] [-c] args...‘
exit 1;;
esac
done
echo $OPTIND
shift $(($OPTIND - 1))
# 输入: ./my.sh -a -a -b
# 输出:
# this is a
# this is b
# 4
# 输入: ./my.sh -a -b 5 -c
# 输出:
# this is a
# this is b
# args b is 5
# this is c
# 5
# 输入: ./my.sh -acb 4
# this is a
# this is c
# this is b
# args b is 4
# 3
数组
name[0]=abc;
name[1]=def;
name[2]=ghi;
## ==
name=(abc def ghi)
## ==
name=([0]=abc [1]=def [2]=ghi)
for i in "${name[@]}"; do
echo $i
done
文件描述符
<> FILE: 文件作为输入和输出
2> FILE: 将错误写入文件 或者 2>>FILE
&> FILE: 定向标准输出和标准错误到 FILE 或者 &>>FILE
2>&1: 把 2 输出到 1
2<&0: 把 2 出入到 0
模式匹配
${VALUE#pattern} |
匹配以 pattern 开头的部分,只匹配一次 |
${VALUE##pattern} |
匹配以 pattern 开头的部分,匹配至多次 |
${VALUE%pattern} |
匹配以 pattern 结尾的部分,只匹配一次 |
${VALUE%%pattern} |
匹配以 pattern 结尾的部分,匹配至多次 |
${VALUE/OLDSTRING/NEWSTRING} |
替换字符串,只替换一个匹配到 |
${VALUE//OLDSTRING/NEWSTRING} |
替换字符串,替换全部匹配到 |
# 从前面开始往后面删除匹配到的, 留下最后没被匹配的
% 从后面往前面开始删除, 留下前面的
temp=/home/sunx/Work/bin
echo ${temp#*/} # home/sunx/Work/bin
echo ${temp%%/*} #
echo ${temp##*/} # bin
echo ${temp%/*} # /home/sunx/Work/bin
temp=test.c
file1=${temp#*\.}
echo ${file1} # c
file2=${temp%*\.*} # test
temp=test.c.cpp
file=${temp#*\.} # c.cpp
file=${temp##*\.} # cpp
file=${temp%\.*} # test.c
file=${temp%%\.*} #
脚本控制流
test
文件属性
-e |
该名字是否存在 |
-f |
该名字是否存在且为档案 file |
-d |
改名字是否存在且为目录 dirctory |
-b |
该名字是否存在且为 block device 装置 |
-c |
该名字是否存在且为 charcter device |
-S |
该名字是否存在且为 socket 档案 |
-p |
该名字是否存在且为 FIFO(pipe) 档案 |
-L |
该当名是否存在且为一个 link 档案 |
文件权限
2 个文件比较
-nt |
(newer than)file1 是否比 file2 新 |
-ot |
(older than)file1 是否比 file2 旧 |
-ef |
是否相等, 判断 hard link 经常使用 |
2 个数值比较
-eq |
是否相等 |
-ne |
not equal |
-gt |
(greater than)大于 |
-lt |
(less than) 小于 |
-ge |
(greater than or equal) 大于等于 |
-le |
(less than or equal) 小于等于 |
字符串
test -z string |
判定字符串是否为 0? 若 string 为空字符串, 则是 true |
test -n string |
判定字符串是否非 0? |
test str1 = str2 |
判定 str1 是否等于 str2 |
test str1 != str2 |
判定是否不等,一定要加空格 |
判断相等的时候 等于号左右留空格, 否则被当成赋值.
test 中使用逻辑判断
-a |
test -r file -a -x file |
|
-o |
test -r file -o -x file |
|
! |
test ! -x file, 当 file 不具有 x 权限时, 才是 true |
|
[] 判断
[] 等价于 test
[ "$HOME" == "$MAIL" ]
# 在 bash 里面用 = 和用 == 是一样的
# [ ] 前后都要加空格
read -p "Please input (Y/N): " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don‘t know what your choice is" && exit 0
[ "$yn" == "Y" -o "$yn" == "y" ]
# 等价于
[ "$yn" == "Y" ] || [ "$yn" == "y"]
if 语句
if [ 条件判断式 ]; then
...
fi
read -p "please input(Y/N):" yn
if [ "$yn" == "Y" ]||[ "$yn" == "y" ]; then
echo "ok, yes continue"
exit 0
fi
if [ 条件判断式 ]; then
...
else
...
fi
if [ 条件判断式 ]; then
...
elif [ 条件判断式二 ]; then
...
else
...
fi
for
for animal in dog cat elephant; do
echo "there are ${animal}s..."
done
# dogs
# cats
# elephants
users=$(cut -d ‘:‘ -f1 /etc/passwd)
# users=`cut -d ‘:‘ -f1 /etc/passwd`
for usename in $users; do
id $username
finger $username
done
# $((...)) 对数学表达式求值
# echo $((2*10)) 20
# echo $((2**3)) 8
# echo $((s)) # 结果是 0, 说明这样的操作 shell 会自动给他 0,接下来看下面
for((i=0; i<=10; ++i)) do
s=$(($s+$i)) # s = s + i
done
while
while [ "$yn" != "yes" -a "$yn" != "YES" ]; do
read -p "please input yes/YES to stop this program: " yn
done
echo "ok! you input the correct answer."
until
until [ "$yn" == "yes" -o "$yn" == "YES" ]; do
read -p "please input yes/YES to stop this program: " yn
done
echo "ok! you input the correct answer."
# 直到条件满足才退出循环.
case
case $1 in
"hello")
echo "hello, how are you?"
;;
"")
echo "you must input parameters, example: {$0 someword}"
;;
*) # 相当于 C 语言的 default
echo "usae $0 {hello}"
;;
# 也可以在 case 里面用 | 來表示或, 例如
case $1 in
123 | 456)
...
esac # end
select
select name in LIST; do
...
done
temp=$(ls *.c) # a.c b.c
select file in $temp; do
if [ $file == "a.c" ]; then
echo "a.c"; fi
if [ $file == "b.c" ]; then
echo "b.c"; fi
done
1) a.c
2) b.c
#? 1
a.c
#? 2
b.c
#? 3
bash: [: ==: unary operator expected
bash: [: ==: unary operator expected
#? 1
a.c
#?
脚本函数
如果从别的文件中调用函数, 例文件名字是 a.sh
. /PATH_TO/a.sh
或者是
source ./PATH_TO/a.sh
function FUNCTNAME() {
}
FUNCTNAMENAME() {
}
## 这 2 种形式都是可以声明和定义一个函数的
unset -f FUNCTNAME
function afunc {
echo in function : $0 $1 $2
var1="in function"
echo var1: $var1
}
var1="outside function"
echo var1: $var1
echo $0: $1 $2
afunc funcarg1 funcarg2
echo var1: $var1
echo $0: $1 $2
# var1: outside function
# ./Function.sh: arg1 arg2
# in function : ./Function.sh funcarg1 funcarg2 # 从这里开始调用函数
# var1: in function
# var1: in function # var1 还是 in function
# ./Function.sh: arg1 arg2
function afunc {
# local var1
echo in function : $0 $1 $2
# var1="in function" # 如果这句话被注释掉, 下面以行的 var1 的值就变成了空, 但是如果同时把 local 的声明也注释掉就是 outside...
echo var1: $var1
} # 由上面的注释可以知道, 再脚本里面定义的变量可以在函数里面使用, 但是如果函数定义了该变量就不行了
var1="outside function"
echo var1: $var1
echo $0: $1 $2
afunc funcarg1 funcarg2
echo var1: $var1
echo $0: $1 $2
# var1: outside function
# ./Function.sh: arg1 arg2
# in function : ./Function.sh funcarg1 funcarg2
# var1: in function
# var1: outside function # var1 的值还是函数的, 函数外的 var1 的值没有影响
# ./Function.sh: arg1 arg2
function printit() {
echo -n "Your choice is $1"
}
echo "This program will print your selection !"
case $1 in
"one")
printit; echo $1 | tr ‘a-z‘ ‘A-Z‘ # 将参数做大小写转换!
;;
"two")
printit; echo $1 | tr ‘a-z‘ ‘A-Z‘
;;
"three")
printit; echo $1 | tr ‘a-z‘ ‘A-Z‘
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac
##############上面是程序的的参数, ..区别于函数的的参数. .........###############
## 程序的参数是在 shell 命令中跟在脚本名字后面的, 函数的参数是在脚本里面调用函数时候, 跟在脚本后面的
################下面是函数的参数, ..区别于程序的参数. .........#################
function printit() {
echo -n "Your choice is $1 "
echo "This program will print your selection !"
case $1 in
"one")
printit 1; echo $1 | tr ‘a-z‘ ‘A-Z‘ # 将参数做大小写转换!
;;
"two")
printit 2; echo $1 | tr ‘a-z‘ ‘A-Z‘
;;
"three")
printit 3; echo $1 | tr ‘a-z‘ ‘A-Z‘
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac
}
printit one
# result
# Your choice is one This program will print your selection !
# Your choice is 1 This program will print your selection ! # 注意 printit 1 也会继续调用函数
# Usage a.sh {one|two|three}
# ONE
脚本调试
sh [-nvx] FILE
-n |
不执行,仅检查语法问题 |
-v |
执行前,先输出脚本 |
-x |
将使用到的脚本输出 |
cat a.sh
echo "hello" || echo "123"
sh -n a.sh # 检查语法问题, 没输出,说明没问题,似乎没用 :D
sh -v a.sh
echo "hello" || echo "123"
hello
sh -x a.sh
+ echo hello
hello
时间: 2024-12-26 22:56:06