Linux shell script

来源:互联网 发布:mac搜狗输入法不能用 编辑:程序博客网 时间:2024/05/20 20:04

ShellSyntax

common

Shell中的引号,反引号,双引号

1 当shell碰到第一个单引号时,它忽略掉其后直到右引号的所有特殊字符

2 双引号只要求忽略大多数,具体说,括在双引号中的三种特殊字符不被忽略:$,\,`,即双引号会解释字符串的特别意思,而单引号直接使用字符串

 

 

source命令是在当前shell中执行,所以定义的变量可以直接使用,例如:

source a.sh ; 其中a.sh中定义了KKK="123"

如果直接执行./a.sh 或者 sh ./a.sh,就是重新开辟子shell执行,所以KKK无法被父shell访问到。

export命令作用是将父shell的变量可以传递给子shell,而子shell的变量永远无法传递给父shell,除非用source

 

Useful commands:

export LOCALVERSION="SEC_BUILD_OPTION" //exportvariable

env --unset=LOCALVERSION > /dev/null  //remove variable

 

eg.

TOPDIR := $(shell pwd)/../..

 

variable

 

echo "go here $LINENO"

~ :表示当前用户的根目录,它是一个变量

~jerry:表示jerry的根目录

 

通配符的使用:

Like: cp test[1-5]

Like: cd /lib/modules/’uname –r’/kernel/drivers

等价于 cd /lib/modules/$(uname –r)/kernel/drivers

 

ShellVariables:

#use“man bash” by searching “Shell Variables”

likebelows:

echo$LINNO $PPID $PWD and etc.

 

NOTE:

"linux shell:这里的%% * 是什么意思?"

诸如此类的问题,在man bash可以找到’详细说明,查找ParameterExpansion这段

 

${},##和%%

為了完整起見,我這裡再用一些例子加以說明 ${ } 的一些特異功能:

假設我們定義了一個變量為:

file=/dir1/dir2/dir3/my.file.txt

我們可以用 ${ } 分別替換獲得不同的值:

${file#*/}:拿掉第一條 / 及其左邊的字串:dir1/dir2/dir3/my.file.txt

${file##*/}:拿掉最後一條 / 及其左邊的字串:my.file.txt

${file#*.}:拿掉第一個 .  及其左邊的字串:file.txt

${file##*.}:拿掉最後一個 .  及其左邊的字串:txt

${file%/*}:拿掉最後條 / 及其右邊的字串:/dir1/dir2/dir3

${file%%/*}:拿掉第一條 / 及其右邊的字串:(空值)

${file%.*}:拿掉最後一個 .  及其右邊的字串:/dir1/dir2/dir3/my.file

${file%%.*}:拿掉第一個 .  及其右邊的字串:/dir1/dir2/dir3/my

記憶的方法為:

#是去掉左邊(在鑑盤上 # 在$ 之左邊)

%是去掉右邊(在鑑盤上 % 在$ 之右邊)

單一符號是最小匹配﹔兩個符號是最大匹配。

${file:0:5}:提取最左邊的 5 個字節:/dir1

${file:5:5}:提取第 5 個字節右邊的連續 5 個字節:/dir2

 

我們也可以對變量值裡的字串作替換:

${file/dir/path}:將第一個 dir 提換為 path:/path1/dir2/dir3/my.file.txt

${file//dir/path}:將全部 dir 提換為 path:/path1/path2/path3/my.file.txt

 

利用 ${ } 還可針對不同的變數狀態賦值(沒設定、空值、非空值):

${file-my.file.txt}:假如 $file 沒有設定,則使用 my.file.txt 作傳回值。(空值及非空值時不作處理)

${file:-my.file.txt}:假如 $file 沒有設定或為空值,則使用 my.file.txt 作傳回值。 (非空值時不作處理)

${file+my.file.txt}:假如 $file 設為空值或非空值,均使用 my.file.txt 作傳回值。(沒設定時不作處理)

${file:+my.file.txt}:若 $file 為非空值,則使用 my.file.txt 作傳回值。 (沒設定及空值時不作處理)

${file=my.file.txt}:若 $file 沒設定,則使用 my.file.txt 作傳回值,同時將 $file 賦值為my.file.txt 。 (空值及非空值時不作處理)

${file:=my.file.txt}:若 $file 沒設定或為空值,則使用 my.file.txt 作傳回值,同時將 $file 賦值為my.file.txt 。 (非空值時不作處理)

${file?my.file.txt}:若 $file 沒設定,則將 my.file.txt 輸出至STDERR。 (空值及非空值時不作處理)

${file:?my.file.txt}:若 $file 沒設定或為空值,則將 my.file.txt 輸出至 STDERR。(非空值時不作處理)

 

tips:

以上的理解在於, 你一定要分清楚 unset 與null 及 non-null 這三種賦值狀態.

一般而言, : 與 null 有關,若不帶 : 的話, null 不受影響,若帶 : 則連 null 也受影響.

 

還有哦,${#var} 可計算出變量值的長度:

${#file}可得到 27 ,因為 /dir1/dir2/dir3/my.file.txt 剛好是 27 個字節...

 

takea instance:

howard@0[script]$ x=*
howard@0[script]$ echo $x
hello.sh menus.sh misc.sh phonebook tshift.sh
howard@0[script]$ echo '$x'
$x
howard@0[script]$ echo "$x"
*
这个例子可以看出无引号、单引号和双引号之间的区别。在最后一种情况中,双引号告诉shell在引号内照样进行变量名替换,所以shell把$x替换为*,因为双引号中不做文件名替换,所以就把*作为要显示的值传递给echo。
对于第一种情况需要进一步说明,shell在给变量赋值时不进行文件名替换(这从第三种情况中也能看出来),各步骤发生的精确次序如下:
shell 扫描命令行,把x的值设为星号*; shell再次扫描命令行,碰到星号*,把它替换成当前目录下的文件清单; shell启动执行echo命令,把文件清单作为参数传递给echo. 这个赋值的先后次序非常重要:shell先作变量替换,然后作文件名替换,最后把这行处理为参数

 

3. 反引号(``)
命令替换是指shell能够将一个命令的标准输出插在一个命令行中任何位置。shell中有两种方法作命令替换:把shell命令用反引号或者$(...)结构括起来,其中,$(...)格式受到POSIX标准支持,也利于嵌套。
howard@0[script]$ echo The date and time is `date`
The date and time is 三 6月 15 06:10:35 CST 2005
howard@0[script]$ echo Your current working directory is $(pwd)
Your current working directory is /home/howard/script  
4. 反斜杠 backslash-escaped( \ )
反斜杠一般用作转义字符,或称逃脱字符,linux如果echo要让转义字符发生作用,就要使用-e选项,且转义字符要使用双引号
echo -e "\n"
反斜杠的另一种作用,就是当反斜杠用于一行的最后一个字符时,shell把行尾的反斜杠作为续行,这种结构在分几行输入长命令时经常使用。

 

深入研究shell命令行符号解析:

假如我们需要在command line中将这些保留字符的功能关闭的话,就需要quoting 处理了。
在 bash 中,常用的 quoting 有如下三种方法:
* hard quote:' ' (单引号),凡在hard quote 中的所有 meta 均被关闭。
* soft quote: " " (双引号),在 soft quoe 中大部份meta 都会被关闭,但某些则保留(如 $ )。(注:在soft quote中被豁免的具体meta清单,我不完全知道,有待大家补充,或透过实作来发现及理解。)
* escape : \ (反斜线),只有紧接在escape (跳脱字符)之后的单一 meta 才被关闭。
下面的例子将有助于我们对 quoting 的了解:
$ A=B C   # 空格键未被关掉,作为IFS 处理。
$ C: command not found. (FIXME)
$ echo $A

$ A="B C"   # 空格键已被关掉,仅作为空格键处理。
$ echo $A
B C
在第一次设定 A 变量时,由于空格键没被关闭,command line 将被解读为:
* A=B 然后碰到<IFS>,再执行 C 命令
在第二次设定 A 变量时,由于空格键被置于 soft quote 中,因此被关闭,不再作为 IFS :
* A=B<space>C
事实上,空格键无论在 soft quote 还是在 hard quote 中,均会被关闭。Enter 键亦然:
$ A='B
> C
> '
$ echo $A
B
C
在上例中,由于<enter>被置hard quote当中,因此不再作为CR字符来处理。
这里的<enter>单纯只是一个断行符号(new-line)而已,由于 command line 并没得到 CR 字符,因此进入第二个 shell prompt(PS2,以>符号表示),command line并不会结束,直到第三行,我们输入的 <enter> 并不在hard quote里面,因此并没被关闭,此时,commandline碰到 CR 字符,于是结束、交给 shell 来处理。
上例的 <enter> 要是被置于 soft quote 中的话,也会同样被关闭,用 escape 亦可:
$ A=B\
> C\
>
$ echo $A
B
C
上例中,第一个 <enter> 跟第二个 <enter> 均被 escape 字符关闭了,因此也不作为 CR 来处理,但第三个<enter> 由于没被跳脱,因此作为CR 结束 command line 。
至于 soft quote 跟 hard quote 的不同,主要是对于某些meta 的关闭与否,以 $ 来作说明:
$ A=B\ C
$ echo "$A"
B C
$ echo '$A'
$A
在第一个 echo 命令行中,$ 被置于soft quote 中,将不被关闭,因此继续处理变量替换,因此 echo 将 A 的变量值输出到荧幕,也就得到 "B C" 的结果。在第二个 echo 命令行中,$被置于 hard quote 中,则被关闭,因此 $ 只是一个 $ 符号,并不会用来作变量替换处理,因此结果是$ 符号后面接一个 A 字母:$A 。
--------------------------------------
练习与思考:如下结果为何不同?
$ A=B\ C
$ echo '"$A"'   # 最外面的是单引号
"$A"
$ echo "'$A'"   # 最外面的是双引号
'B C'
(提示:单引号及双引号,在 quoting 中均被关?#93;了。)
--------------------------------------
在CU的shell版里,我发现有很多初学者的问题,都与quoting理解的有关。比方说,若我们在awk或sed的命令参数中调用之前设定的一些变量时,常会问及为何不能的问题。
要解决这些问题,关键点就是:
* 区分出 shell meta 与 command meta
前面我们提到的那些 meta ,都是在 command line 中有特殊用途的,比方说 { } 是将其内一系列 command line 置于不具名的函式中执行(可简单视为 command block ),但是,awk 却需要用{ } 来区分出 awk 的命令区段(BEGIN, MAIN, END)。 若你在 command line 中如此输入:
$ awk {print $0} 1.txt
由于 { } 在 shell 中并没关闭,那shell 就将 {print $0} 视为 command block,但同时又没有"; "符号作命令区隔,因此就出现 awk 的语法错误结果。
要解决之,可用 hard quote :
$ awk '{print $0}' 1.txt
上面的 hard quote 应好理解,就是将原本的 {、<space>、$(注三)、} 这几个 shellmeta 关闭,避免掉在 shell 中遭到处理,而完整的成为 awk 参数中的command meta 。( 注:而其中的$0是awk内建的field number,而非awk的变量,awk自身的变量无需使用$。)
要是理解了 hard quote 的功能,再来理解 soft quote与 escape 就不难:
awk "{print \$0}" 1.txt
awk \{print\ \$0\} 1.txt
然而,若你要改变 awk 的 $0 的0 值是从另一个 shell 变量读进呢?比方说:已有变量 $A 的值是0,那如何在 command line 中解决 awk 的 $$A 呢?你可以很直接否定掉hard quoe 的方案:
$ awk '{print $$A}' 1.txt
那是因为 $A 的 $ 在hard quote 中是不能替换变量的。
聪明的读者(就是你!),经过本章学习,我想,应该可以解释为何我们可以使用如下操作了吧:
A=0
awk "{print \$$A}" 1.txt
awk \{print\ \$$A\} 1.txt
awk '{print $'$A'}' 1.txt
awk '{print $'"$A"'}' 1.txt     # 注:"$A" 包在 soft quote 中
或许,你能举出更多的方案呢.... ^_^

 

 

= : 设定变量。
$ : 作变量或运算替换(请不要与 shell prompt 搞混了)。
> :重导向 stdout。
< :重导向 stdin。
|:命令管线。
& :重导向 file descriptor ,或将命令置于背境执行。
( ):将其内的命令置于 nested subshell 执行,或用于运算或命令替换。
{ }:将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围。
; :在前一个命令结束时,而忽略其返回值,继续执行下一个命令。
&& :在前一个命令结束时,若返回值为 true,继续执行下一个命令。
|| :在前一个命令结束时,若返回值为 false,继续执行下一个命令。
!:执行 history 列表中的命令

 

!command : the last command with parameter

Mount:查看当前文件系统的挂载情况

      e.g. mount -orw,remount /dev/sdd1

      e.g. sudo mount后,如何让普通用户有写权限:

      sudo mount/dev/sdd1 ~/2G -O umask=000

 

Less : 使用管道命令less来查看:like history|less , thenpress G to jump to the last of line

 

ll location* //list files name contains location

 

---------------------------------------------------------------

programming commands:

nm : list symbols from object files

TIMEFORMAT="" time $command //show elapsed time

 

多个命令一块迅速运行:使用连接符,like jobs; bg %1; jobs

 

---------------------------------------------------------------

ls -al | grep ^d

tree

 

git diff | grep "+++\|---" | more

--help / man / info

add "|less" at the end of commands

ls -R equals find

 

locate vmrtke.x.bz2|xargs du

lsof -i :80 –》 查询使用80端口的linux进程

 

ls –l filename  //checkfilename info

 

 

cat  由第一行开始显示档案内容 
tac  从最后一行开始显示,可以看出 tac 是 cat 的倒着写! 
more 一页一页的显示档案内容 
less 与 more 类似,但是比 more 更好的是,他可以往前翻页! 
head 只看头几行 
tail 只看尾巴几行 
nl   显示的时候,顺道输出 行号! 
od   以二进制的方式读取档案内容!

Chapter 13      Shell script 

 

Test 命令使用

Eg:test –e/dmtsai && echo “exist” || echo “not exist”

 

Test 的命令扩展:page268

Eg:

ead -p "input a filename" filename

test -z $filename && echo "you must input afilename" && exit 0

test ! -e $filename && echo "The filename$filename DO NOT exist" && exit 0

test -f $filename && filetype="regularefile"

test -d $filename && filetype="directory"

test -r $filename && perm="readable"

test -w $filename && perm="$perm writable"

test -x $filename && perm="$perm executable"

echo "The filename: $filename is a $filetype"

echo "And the permission are : $perm"

 

判断符号 []

Eg: [ $string1 == $string2 ]  (注意空格)

最好用双引号,like [“$string1” == “$string2” ]

相当于: test$string1 = $string2

 

eg: 

read -p "Please input (Y/N): " yn

[ "$yn"== "Y" -o "$yn" == "y" ] && echo"OK, contine" && exit 0

[ "$yn" == "N" -o "$yn" =="n" ] && echo "Oh, interrupt!" && exit 0

echo "I don't know what is your choise" &&exit 0

 

Shell脚本的默认变量:$0,$1, $2, $3 see more in page 271

 

条件判断:

(1) if [条件判断表达式1] ;then

当条件判断表达式1成立时,可以执行的命令

elif[条件判断表达式2] ;then

当条件判断表达式2成立时,可以执行的命令

else

当条件判断表达式不成立时,可以执行的命令

fi

eg:

if [ “$yn” == “Y” ] || [ “$yn” == “y” ]; then

      echo “OK”

fi

 

(2) case .. esac 判断:

case ${variable name} in

“first variable’s value”)

      segament

      ;;

“second variable’s value”)

      segament

      ;;

*)

      # the other case

      exit 1

      ;;

esac

 

eg:

case $1 in

      “hello”)

                  echo“Hello”

                  ;;

      “”)

                  echo“you must input parameters”

                  ;;

      *)

                  echo“usage $1 {hello}”

                  ;;

esac

 

(3) function

语法:

function fname() {

      segament body

}

通过fname对函数进行调用。

函数有内置参数:函数名:$0;$1,$2,$3等是函数调用时后面跟着的参数list

 

(4) 循环

while [ condition ]

do

      segament body

done

 

until [ condition ]

do

      segament body

done

 

Shell script debugging method:

command: sh [-nvx] scripts.sh

Shell例子& grammar

变量加1操作的几种方式:

let "var+=1" 

var=$[$var+1]    

var=`expr $var + 1`#注意加号两边的空格

 

simple loop example:

  1 #!/bin/bash

  2 num=0

  3

  4 while :;

  5 do

  6     adbreboot;

  7    sleep 5;

  8    num=`expr $num + 1`

  9    echo ${num}

 10 done

 

##############################################

.----- < 特殊变量 > -----

$0                   正在被执行命令的名字。对于shell 脚本而言,这是被激活命令的路径

$n                 该变量与脚本被激活时所带的参数相对应。n 是正整数,与参数位置相对应($1,$2...)

$#                 提供脚本的参数号

$*                 所有这些参数都被双引号引住。若一个脚本接收两个参数,$*等于 $1$2

$@               所有这些参数都分别被双引号引住。若一个脚本接收到两个参数,$@等价于 $1$2

$?                 前一个命令执行后的退出状态

$$                 当前shell 的进程号。对于shell 脚本,这是其正在执行时的进程ID

$!                 前一个后台命令的进程号

$-                 显示shell使用的当前选项,与 set命令功 能相同

 

Example1 统计内存

meminfo.sh //统计内存信息的shell脚本

 

---------------------meminfo.sh start ---------------------

#!/bin/bash

 

i=0

END=0

 

while [ $i != "360" ]

do

sleep 10

adb shell cat proc/meminfo | grep "MemFree"

i=`expr $i + 1`

done

echo

exit 0

---------------------meminfo.sh end ---------------------



一句话循环实例

while [ 1 ];do sleep 1;du -sh;done

例子 case

 

#b1=0

#b2=0

#case ${i} in

#     "0")

#                    echo "1"

#                    b1=`cat/sys/class/power_supply/battery/current_now`

#                    echo ${b1};;

#     "1")

#                    echo "2"

#                    b2=`cat/sys/class/power_supply/battery/current_now`

#                    echo ${b2};;

#esac

例子2 循环操作

while [ 1 -eq 1 ] ; do sleep 10; ping -c 3 192.168.13.74; done

//注意有些sh并不解析==和!=

再如:

#!/bin/sh

 

i=0

 

while [ $i!= "1" ]

 

do

 

sleep 8

ifconfigeth0 192.168.13.222

ping -c 3192.168.13.74

 

done

 

exit 0

 

 

 

 

 

while :; do

...

done

 

 

 

while [1  -eq 1 ]

do

ifconfigeth0 192.168.13.75

sleep10

done

 

 

for loop in `find`; do strings$loop | grep pvr_drv_video;if [ $? -eq 0 ];then echo $loop ~~; fi; done

等价于:

for loop in `find`;

    dostrings $loop | grep pvr_drv_video;

    if[ $? -eq 0 ];then 

                echo$loop ~~;

    fi;

    done

 

 

//输入Enter再继续进行

echo -n Press Enter to view thelicense

read dummy

echo

Shell Skill

dir=`echo ${DIR}|sed "s/^.\///"`  

#过滤DIR变量中的字符时,要加入echo做管道前的处理

含有类似$PATH的变量时,要用单引号,而不是双引号

0 0
原创粉丝点击