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)/../..
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把行尾的反斜杠作为续行,这种结构在分几行输入长命令时经常使用。
假如我们需要在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 然后碰到
在第二次设定 A 变量时,由于空格键被置于 soft quote 中,因此被关闭,不再作为 IFS :
* A=B
事实上,空格键无论在 soft quote 还是在 hard quote 中,均会被关闭。Enter 键亦然:
$ A='B
> C
> '
$ echo $A
B
C
在上例中,由于
这里的
上例的
$ A=B\
> C\
>
$ echo $A
B
C
上例中,第一个
至于 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 应好理解,就是将原本的 {、
要是理解了 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 以二进制的方式读取档案内容!
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
变量加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命令功 能相同
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
#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
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
dir=`echo ${DIR}|sed "s/^.\///"`
#过滤DIR变量中的字符时,要加入echo做管道前的处理
含有类似$PATH的变量时,要用单引号,而不是双引号