Posts tagged Shell
获得Shell脚本所在目录的绝对路径
0要得到正在执行的程序/脚本自身所存放的绝对路径,在 PHP 里面可以用 dirname(realpath(__FILE__)) ; C# 则有 System.Windows.Forms.Application.StartupPath ; java 似乎没有什么比较直接的方法,只能利用 CodeSource 来间接获取 。而在 linux shell 脚本里面如果想得到当前脚本文件存放的绝对路径,也没有太现成的命令可以调用,不过可以通过下面的语句来获取:
baseDirForScriptSelf=$(cd “$(dirname “$0″)”; pwd)
echo “full path to currently executed script is : ${baseDirForScriptSelf}”
虽说大部分情况下我们并不需要这样的绝对路径来完成工作;但如果要把多个脚本、数据文件等内容打包作为一个整体来交付别人使用,又希望不论用户拷贝到哪个目录下执行脚本都能够正确的找到这个包里面的其他内容的话,用这样的脚本来自动定位包的根目录应该是个比较鲁棒的做法。
Shell程序设计的流程控制
0和其他高级程序设计语言一样,Shell提供了用来控制程序执行流程的命令,包括条件分支和循环结构,用户可以用这些命令创建非常复杂的程序。
与传统语言不同的是,Shell用于指定条件值的不是布尔运算式,而是命令和字串。
1.测试命令
test命令用于检查某个条件是否成立,它可以进行数值、字符和文件3个方面的测试,其测试符和相应的功能分别如下。
(1)数值测试:
-eq 等于则为真。
-ne 不等于则为真。
-gt 大于则为真。
-ge 大于等于则为真。
-lt 小于则为真。
-le 小于等于则为真。
(2)字串测试:
= 等于则为真。
!= 不相等则为真。
-z字串 字串长度伪则为真。
-n字串 字串长度不伪则为真。
(3)文件测试:
-e文件名 如果文件存在则为真。
-r文件名 如果文件存在且可读则为真。
-w文件名 如果文件存在且可写则为真。
-x文件名 如果文件存在且可执行则为真。
-s文件名 如果文件存在且至少有一个字符则为真。
-d文件名 如果文件存在且为目录则为真。
-f文件名 如果文件存在且为普通文件则为真。
-c文件名 如果文件存在且为字符型特殊文件则为真。
-b文件名 如果文件存在且为块特殊文件则为真。
另外,Linux还提供了与(!)、或(-o)、非(-a)三个逻辑操作符,用于将测试条件连接起来,其优先顺序为:!最高,-a次之,-o最低。
同时,bash也能完成简单的算术运算,格式如下:
$[expression]
例如:
var1=2
var2=$[var1*10+1]
则var2的值为21。
2.if条件语句
Shell程序中的条件分支是通过if条件语句来实现的,其一般格式为:
if 条件命令串
then
条件为真时的命令串
else
条件为假时的命令串
fi
3.for循环
for循环对一个变量的可能的值都执行一个命令序列。赋给变量的几个数值既可以在程序内以数值列表的形式提供,也可以在程序以外以位置参数的形式提供。for循环的一般格式为:
for变量名 [in数值列表]
do
若干个命令行
done
变量名可以是用户选择的任何字串,如果变量名是var,则在in之后给出的数值将顺序替换循环命令列表中的$var。如果省略了in,则变量var的取值将是位置参数。对变量的每一个可能的赋值都将执行do和done之间的命令列表。
4.while和until循环
while和until命令都是用命令的返回状态值来控制循环的。While循环的一般格式为:
while
若干个命令行1
do
若干个命令行2
done
只要while的“若干个命令行1”中最后一个命令的返回状态为真,while循环就继续执行do…done之间的“若干个命令行2”。
until命令是另一种循环结构,它和while命令相似,其格式如下:
until
若干个命令行1
do
若干个命令行2
done
until循环和while循环的区别在于:while循环在条件为真时继续执行循环,而until则是在条件为假时继续执行循环。
Shell还提供了true和false两条命令用于创建无限循环结构,它们的返回状态分别是总为0或总为非0。
5.case条件选择
if条件语句用于在两个选项中选定一项,而case条件选择为用户提供了根据字串或变量的值从多个选项中选择一项的方法,其格式如下:
case string in
exp-1)
若干个命令行1
;;
exp-2)
若干个命令行2
;;
……
*)
其他命令行
esac
Shell通过计算字串string的值,将其结果依次和运算式exp-1, exp-2等进行比较,直到找到一个匹配的运算式为止。如果找到了匹配项,则执行它下面的命令直到遇到一对分号(;;)为止。
在case运算式中也可以使用Shell的通配符(“*”、“?”、“[ ]”)。通常用 * 作为case命令的最后运算式以便在前面找不到任何相应的匹配项时执行“其他命令行”的命令。
6.无条件控制语句break和continue
break用于立即终止当前循环的执行,而contiune用于不执行循环中后面的语句而立即开始下一个循环的执行。这两个语句只有放在do和done之间才有效。
7.函数定义
在Shell中还可以定义函数。函数实际上也是由若干条Shell命令组成的,因此它与Shell程序形式上是相似的,不同的是它不是一个单独的进程,而是Shell程序的一部分。函数定义的基本格式为:
functionname
{
若干命令行
}
调用函数的格式为:
functionname param1 param2…
Shell函数可以完成某些例行的工作,而且还可以有自己的退出状态,因此函数也可以作为if, while等控制结构的条件。
在函数定义时不用带参数说明,但在调用函数时可以带有参数,此时Shell将把这些参数分别赋予相应的位置参数$1, $2, …及$*。
8.命令分组
在Shell中有两种命令分组的方法:()和{}。前者当Shell执行()中的命令时将再创建一个新的子进程,然后这个子进程去执行圆括弧中的命令。 当用户在执行某个命令时不想让命令运行时对状态集合(如位置参数、环境变量、当前工作目录等)的改变影响到下面语句的执行时,就应该把这些命令放在圆括弧 中,这样就能保证所有的改变只对子进程产生影响,而父进程不受任何干扰。{}用于将顺序执行的命令的输出结果用于另一个命令的输入(管道方式)。当我们要 真正使用圆括弧和花括弧时(如计算运算式的优先顺序),则需要在其前面加上转义符()以便让Shell知道它们不是用于命令执行的控制所用。
9.信号
trap命令用于在Shell程序中捕捉信号,之后可以有3种反应方式:
(1)执行一段程序来处理这一信号。
(2)接受信号的默认操作。
(3)忽视这一信号。
trap对上面3种方式提供了3种基本形式:
第一种形式的trap命令在Shell接收到与signal list清单中数值相同的信号时,将执行双引号中的命令串。
trap ‘commands‘ signal-list
trap "commands" signal-list
为了恢复信号的默认操作,使用第二种形式的trap命令:
trap signal-list
第三种形式的trap命令允许忽略信号:
trap " " signal-list
注意:
(1)对信号11(段违例)不能捕捉,因为Shell本身需要捕捉该信号去进行内存的转储。
(2)在trap中可以定义对信号0的处理(实际上没有这个信号),Shell程序在其终止(如执行exit语句)时发出该信号。< br />
(3)在捕捉到signal-list中指定的信号并执行完相应的命令之后,如果这些命令没有将Shell程序终止的话,Shell程序将继续执行收到信号时所执行的命令后面的命令,这样将很容易导致Shell程序无法终止。
另外,在trap语句中,单引号和双引号是不同的。当Shell程序第一次碰到trap语句时,将把commands中的命令扫描一遍。此时若 commands是用单引号括起来的话,那么Shell不会对commands中的变量和命令进行替换,否则commands中的变量和命令将用当时具体 的值来替换。
(http://www.fanqiang.com)
SHELL之循环语句
01、if语句
2、交互选择
3、循环判断
4、数值运算符
5、…………
if语句格式:
if [ 条件 ]
then
command
else
command
fi
交互选择(N可以为*)
echo -e “提示语言,后边有光标提供输入”c
read VAR
case $VAR in
Y)
command
;;
N)
command
;;
esac
对条件进行循环检查,成立则处理,否则继续检查
a=1
while [ "$a" = "1" ]
do
fileno=`ls -l /list/filename* |wc -l`
if [ "$fileno" = "10" ]
then
a=10
command
else
a=1
sleep 300
fi
done
grep -v www filename 过滤不包含
grep www filename 过滤包含
uniq -u 过滤没有相同行
uniq -d 过滤具有相同行
sort 排序
paste -d”;” filename1 filename2 把文件并列合并并且以;间隔
if [ "a" = "10" ] #a=10
[ "a" -ne "10" ] 同上一行
[ -s filename ] 文件大小大于0
-s 文件大小大于0返回真
-d 是一个目录是返回真
-e 文件或目录存在返回真
-g 存在是SGID返回真
-h 文件是连接文件返回真
-k 文件是粘滞位返回真
-r 文件或目录存在并可读时返回真
-w 文件或目录存在并可写时返回真
-u 文件是SUID返回真
-x 文件是可执行的返回真
-eq 等于
-ne 不等于
-lt 小于
-le 小于等于
-gt 大于
-ge 大于等于
2*3+4|bc 计算前面的数据
ping -w 2 www.163.com 测试2两次
对上一次指令结果判断
$?=0 为真
$?=1 为假
给SHELL后边加参数
XXXX=`echo | wc -c`
cat $HOME/list/file.txt 1>/dev/null 2>/dev/null
OK=$?
if [ "" = "" ] || [ "$XXXX" -lt "4" ] || [ "$OK" -ne "0" ]
then
echo “参数没有输入,输入位数不等于3,file.txt不存在,请重新输入”
exit
fi
一个循环检查
line=1
for i in `cat bb`
do
qq=`echo “scale=2;$i*100″ | bc | awk -F. ”{print }”`
if [ "$qq" -ge "75" ]
then
sed -n “$line”p temp.1 >> bad.1
fi
line=`expr $line + 1` ###每次加1
Linux SHELL if 命令参数说明
0- –b 当file存在并且是块文件时返回真
- -c 当file存在并且是字符文件时返回真
- -d 当pathname存在并且是一个目录时返回真
- -e 当pathname指定的文件或目录存在时返回真
- -f 当file存在并且是正规文件时返回真
- -g 当由pathname指定的文件或目录存在并且设置了SGID位时返回为真
- -h 当file存在并且是符号链接文件时返回真,该选项在一些老系统上无效
- -k 当由pathname指定的文件或目录存在并且设置了“粘滞”位时返回真
- -p 当file存在并且是命令管道时返回为真
- -r 当由pathname指定的文件或目录存在并且可读时返回为真
- -s 当file存在文件大小大于0时返回真
- -u 当由pathname指定的文件或目录存在并且设置了SUID位时返回真
- -w 当由pathname指定的文件或目录存在并且可执行时返回真。一个目录为了它的内容被访问必然是可执行的。
- -o 当由pathname指定的文件或目录存在并且被子当前进程的有效用户ID所指定的用户拥有时返回真。
UNIX Shell 里面比较字符写法:
- -eq 等于
- -ne 不等于
- -gt 大于
- -lt 小于
- -le 小于等于
- -ge 大于等于
- -z 空串
- = 两个字符相等
- != 两个字符不等
- -n 非空串
Shell运算,计算值保留两位小数
0SHELL下是没有小数处理的,能进行运算的只能是-2^30到2^30-1范围的整数,否则溢出。
具体可以用的运算方式有:
[root@root ~]$ i=$[9 / 2]; echo i=$i;
i=4
[root@root ~]$ i=$((9 / 2)); echo i=$i;
i=4
[root@root ~]$ i=`expr 9 / 2` ; echo i=$i;
i=4
很多最小安装的系统不会有expr,可以使用内置命令:
[root@root ~]$ i=let i=9/2 ; echo i=$i;
i=4
如果需要保留小数,比如两位小数,可以使用awk实现,awk真是强大:
[root@root ~]$ i=`awk BEGIN'{printf "%.2fn", 9/2 }'` ; echo i=$i;
i=4.50
[root@root ~]$ i=`awk BEGIN'{ x=9 ; y=4 ; printf "%.2fn", x/y }'` ; echo i=$i;
i=4.50
运算符类型
按位运算符
~, < <, >>, &, |, ^
$[]表示形式告诉 shell 对方括号中的表达式求值

表达式替换
$[ ] 和 $(())
两种格式功能一样,所有的 shell 的求值都是用整数完成
$[ ] 可以接受不同基数的数字
赋值运算符
=、+=、-=、*=、/=、%=、&=、^=、|=、< <=、>>=
SHELL下date命令的用法
0date命令如何获得上星期的日期?
#date -d “-1 week” “+%Y%m%d %A”
举一反三:date命令获得前天,昨天,明天,后天,上个月,下个月的日期
date -d “-2 day” “+%Y%m%d %A” 或 date –date=”2 days ago” “+%Y%m%d %A”
date -d “-1 day” “+%Y%m%d %A” 或 date –date=”1 day ago” “+%Y%m%d %A”
date -d “1 day” “+%Y%m%d %A”
date -d “2 day” “+%Y%m%d %A”
date -d “-1 month” “+%Y%m%d %A”
date -d “1 month” “+%Y%m%d %A”
(更多…)
非常小的shell: 指定行号,插入文本(转)
0使用这个shell可以直接在某个文件的某一行插入指定的文本,很方便. 可以把这个
shell加入PATH中.以下的蓝色部分为代码, 文件名为insert
[Dong@MICRONSKY test]$ more insert
#!/bin/bash
# 从文件的某一行之后插入新行
# FILE 为文件名,LINENUM为行号,TEXT为要插入的文本
(更多…)
Linux下C编程系列–Shell(续)
0shell的输入与输出主要包括:
echo命令
read命令
cat命令
管道
tee命令
标准输入、输出和标准错误
重定向
echo [-e] [-n] string
string : 字符串,可以含 shell 变量、转义符等, 一般用双引号括起来
-e : 让 echo 解释 string 中的转义符
-n : 禁止 echo 输出后输出 NEWLINE(换行)