shell学习笔记

Shell Study Notes

指导思想:

10分钟语法+实操

\ + ENTER   换行

变量

shell变量无需声明即可用,默认空值
于shell,变量常量无区别,用大小写区别
所有变量视为字符串

变量赋值

shell学习笔记_第1张图片
shell var assignments

Here文档

输入到一个命令的标准输入中

cmd << token
text(单双引号视为普通字符)
token

cmd <<-  EOF
text(单双引号视为普通字符,忽略Tab字符,可用来缩进)
EOF

函数

function name {
cmds
return
}


name() {
cmds
return
}

局部变量定义

local variable

#!/bin/bash
ANSWER=maybe
if [ -z “$ANSER” ]; then        #须有“”防止参数为空导致错误($被解读为非空)
        echo “no answer” >&2
        exit 1
fi
if [ “$ANSER” = “yes” ];then
        echo “answer is yes”
elif [ “$ANSER” = “no” ]
        echo “ answer is no”    
else
        echo “answer is maybe”
fi
exit

退出状态

echo $?         显示上一命令退出状态,0成功,非0失败
echo $!         后台最后一次运行的进程pid
#true/false     系统内置命令,以0/1退出状态终止执行

test命令

test expression 更广泛

[ expression ]

测试命令,表达式为true,退出状态0。false非0;特殊符号< > ( )须引号或 \转义

[ [ expression ] ]          支持REG,bash独有
[ [ str=~regex ] ]          string与正则表达式regex匹配为true
[ [ str == foo.* ]]         支持模式匹配*,类似路径名扩展
(())            整数专用,无须扩展,名字识别变量--(( INT == 0 ))

文件测试

[ -e file ]     file 存在为true
[ -f file ]         file存在且为普通文件
[ f1 -nt f2 ]       f1新于fe为true

字符串测试

[ string ]      非空为true
[ -n str ]      str长度>0为true
[ -z str ]      长度=0为true
[ str1 '>'  str2 ]

整数测试

[ int1 -lt int2 ]       <
[ int1 -le int2 ]       <=
[ int1 -ne int2 ]       not =

整数regex=^-?[0-9]+$

控制运算符

mkdir tem && cd tem
[ -d dir ] || mkdir dir

[ $(id –u) == 0 ]为root

读取标准输入

echo -n 不换行输出

$echo -n "123"
$echo "456"

最终输出 123456
而不是
123
456

echo -e   enable interpretation of backslash escapse使能\转义

read [-option] [var…]

-p str      用字符串str为提示符
-t N            N秒超时结束输入 
-s          保密模式,屏幕不显示

若var缺省,系统自动分配shell变量REPLY
不可重定向,echo “$str” | read用法错,REPLY在read执行完后赋值丢失(|开启子shell无法继承父shell)

IFS

IFS=“:” read user pw uid <<< “$file_info”

IFS--Internal Field Separator,shell变量,默认space,Tab,Enter

IFS=:赋值只在read执行周期有效
<<<指示嵌入字符串,其后接字符串

P371 核心代码分析:

file_info=$(grep “^$user_name:” $FILE)
IFS=“:” read user pw uid gid name home shell <<< “$file_info”

grep打印匹配【行】故file_info=$(grep...)返回匹配【行】(内容)
$()为命令替换,同``
$user_name,$FILE为参数扩展
^在‘’内保留特殊意义???
IFS赋值只在该行read命令执行周期有效

常见regex

文件名regex:       ^[-[:alnum:]\._]+$
整数regex:        ^-?[[:digit:]]+$
浮点数regex:       ^-?[[:digit:]]*\.[[:digit:]]+$

if结构

if cmds; then
    cmds
[elif cmds; then
    cmds…]
[else 
    cmds]
fi

while结构

while cmds;
do
    continue;
done

until结构

until cmds;
do
    break;
done

for结构

1)

for var [in words];
do
    cmds
done

words--

  • {A...Z}
  • *.txt
  • $(string $1)
  • 被忽略时var为位置参数

2)

for ((exp1;exp2;exp3));
do
    cmds
done

exp为算术表达式,同C语言

case结构

case word in
    [pattern [| pattern]…)
;;
    a|A)
;;
    ???)
;;
    *)
;;
esac

pattern同路径名扩展:  *?[:[alpha]:]
路径名扩展区别Regex???

循环读取文件

文件到达EOF前为true

1)

while read x y z; 
do
    cmds;
done

2)

sort -k 1,1 k 2n | while read x y z; 
do
    cmds;
done

调试

echo rm * #TESTING  显示扩展,降风险
#!/bin/bash -x      #追踪整个脚本
set -x  #追踪部分脚本
…
set +x
#export PS4='$LINENO + '

位置参数变量

$0-$9,${10}...存储命令行关键字
$0 –- 所执行程序path
$#,${#*},${#@}–- 位置参数个数(自动计算命令行参数数目)
shift?  位参自动下移  瓢or指针?
$(basename $0)--截断路径$0,只留文件名
$* –- 
扩展为1开始参数列;
“$*” 扩展为 字符串“$1 IFS $2...”
$@ –- 
扩展为1开始参数列;
“$@” 扩展为 字符串“$1” “$2”…

参数扩展

可提升效率

${a}        基本参数扩展

${para:-word}   para未设,(表达式)取word值
${para:=word}   para未设,取word值,并赋值
${para:+word}   para未设,取null; or取word值
${para:?err_msg}      para未设,打印err_msg到stderr

${!pre*}        返回pre为前缀的变量名
${!pre@}        返回pre为前缀的变量名
${#para}        返回变量para内字符串长度

${para:offset}          提取para变量内字符串,offset位开始,直到末尾
${para:offset:length}   提取字符串,offset位开始,共length位
                    offset可为负,前须有space,代表字符串末尾开始

${para#pattern} 去除最短匹配;pattern为模式
${para##pattern}    去除最长匹配;pattern为模式

${para%pattern} 去除最短匹配;从字符串尾进行
${para%%pattern}    去除最长匹配;从字符串尾进行

${para/pattern/string}  para内容匹配到pattern,则用string替换
${para//pattern/string} para内容匹配到pattern,则用string全局替换
${para/#pattern/string} para内容头匹配到pattern,则用string替换
${para/%pattern/string} para内容尾匹配到pattern,则用string替换

算术扩展$((exp))

if (( i=5 ))    i赋值5;赋值成功,返回true
for (( i=0;i<5;++i ))

逻辑操作

((exp1?exp2:exp3))  exp1非0执行exp2;or执行exp3

bc

bc < f.bc
bc f.bc
bc <<< “2+2”

数组

bash仅支持一维数组,元素类型限定为字符串和整数

创建数组ar

declare -a ar       

数组赋值

ar[0]=str
color=(red green blue) 
color=([0]=red [1]=green [2]=blue)
ar=str  str赋给ar[0]--无下标引用默认指ar[0]

单元素访问

${ar[0]}        取ar[0]值

所有元素访问

for i in “${a[@]}”; 
do
    echo $i
done

确定数组长度(元素个数)

${#a[@]}

查找数组下标

${!a[@]}
${!a[*]}

数组尾自动增加元素

a+=(x y z…)

数组排序

a_sorted=($(for i in “${a[@]}”; do echo $i; done | sort))

删除

unset 'a[0]'
unset ar

组命令

不丢失环境改变,更快,更少内存
{ cmd1; cmd2; [cmd3;…] } >(<,>>,<<)

子shell

丢失环境改变
(cmd1; cmd2; [cmd3;…]) |

进程替换

<(cmdlist)
>(cmdlist)


echo “foo” | read
echo $REPLY 
显示空。|管道开启子shell,read执行完后REPLY赋值丢失

read < <(echo “foo”)
echo $REPLY 
显示foo。<(echo “foo”)进程替换,将子shell (echo “foo”)输出视为普通文件

while read x y z…; do
cat <<- EOF
Filename:   $z
…
EOF
done < <(ls -l | tail -n +2)

进程替换 输出 定向到 循环 标准输入

trap

trap “echo 'i am ignoring you'” SIGINT…

脚本接收到INT(ctrl-c)信号时,trap执行echo命令

wait命令

async-child &       #父进程--后台执行子进程)
pid=$!          #$!记录后台最后运行进程pid,即子进程)
…
wait $pid           #父进程暂停

管道命名

mkfifo pipe     # prw-r—r--

更多命令在/usr/bin

你可能感兴趣的:(shell学习笔记)