Linux常用shell语法和命令

浏览: 113 发布日期: 2016-11-29 分类: linux

If else

Shell共有三种三种if…else分支

  • if…fi语句
  • if…else…fi语句
  • if…elif…else…fi语句

1、if…else语句

if [ expression ]
    then
Statement(s) to be executed if expression is true
fi

注意:expression 和方括号([ ])之间必须有空格,否则会有语法错误。

if…else也可以写成一行,以命令的方式来运行,像这样:

if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;

2、if条件表达式中的额外判断

字符串的判断

  • str1 = str2 两个字符串有相同内容、长度时为真
  • str1 != str2
  • -n str1 字符串的长度大于0返回真
  • -z str1 字符串的长度等于0时返回真
  • str1 字符串为非空返回真

比较两个字符串是否相等的时候,一般的做法是:

if [ "$test"x = "test"x ]; then 

主要考虑以下几点

  • 使用单个等号
  • 注意到等号两边各有一个空格:这是unix shell的要求
  • 注意到”test"xxtest为空的时候,上面的表达式就变成了x = testx,显然是不相等的。而如果没有这个x,表达式就会报错:[: =: unary operator expected

数字的判断

  • int1 -eq int2 两数相等返回真
  • int1 -ne int2 两数不相等返回真
  • int1 -gt int2 int1大于int2为真
  • int1 -ge int2 int1大于等于int2为真
  • int1 -lt int2 int1小于int2为真
  • int1 -le int2 int1小于等于int2为真

复杂逻辑判断

  • -a 与
  • -o 或
  • ! 非

文件的判断

  • -e filename 如果 filename存在,则为真
  • -d filename 如果 filename为目录,则为真
  • -f filename 如果 filename为常规文件,则为真
  • -L filename 如果 filename为符号链接,则为真
  • -r filename 如果 filename可读,则为真
  • -w filename 如果 filename可写,则为真
  • -x filename 如果 filename可执行,则为真
  • -s filename 如果文件长度不为0,则为真

判断/home/oicq/script/get_random_shm_key.sh是否存在

if [ -e /home/oicq/script/get_random_shm_key.sh ]

判断文件大小是否为空

if [ ! -s ${REMOTE_FILE} ]
    then
        SH_error_msg "${REMOTE_FILE} file is empty"
        return 1
    fi

循环

For

for循环的一般格式为:

for 变量 in 列表
do
    command1
    command2
    ...
    commandN
done

列表 是一组值(数字,字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个赋给变量。

in 列表是可选的,如果不用它,for 循环使用命令行的位置参数

  • 顺序输出当前列表中的数字
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

运行结果如下:

The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
  • 1到100输出
for i in {1..100}  
do  
    echo $i  
done  
  • 显示主目录下以.bash开头的文件
#!/bin/bash
for FILE in $HOME/.bash*
do
   echo $FILE
done

运行结果如下:

/root/.bash_history
/root/.bash_logout
/root/.bash_profile
/root/.bashrc

while

while循环的一般格式为:

while 条件语句

do

action

done;

示例:从文件中读取内容

while read line;do
    echo $line;
done < /etc/hosts;

替换

1、命令替换

命令替换$(cmd)以及`cmd`

$ ls 
a b c 
$ echo $(ls) 
a b c 
$ echo `ls` 
a b c

对于echo $(ls),shell执行时会先执行$(ls),得到其标准输出,在用得到输出替换原来位置上的$(ls),再执行echo命令。

注意:$(cmd)中的命令的错误输出是不会被替换的,只有标准输出

$ var=$(cat d)
cat: d

这里由于文件d在当前目录不存在

2、一串命令的执行()和{}

(){}都是对一串的命令进行执行,但是有所区别:

  • ()只是对一串命令重新开一个子shell进行执行
  • {}对一串命令在当前shell执行
  • (){}都是把一串的命令放在括号里面,并且命令之间用;号隔开
  • ()最后一个命令可以不用分号
  • {}最后一个命令要用分号
  • {}的第一个命令和左括号之间必须要有一个空格
  • ()里的各命令不必和括号有空格
  • (){}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令
$ var=test 
$ (var=notest; echo $var) ###变量var值为notest,此是在子shell中有效 
notest 
$ echo $var ###父shell中值仍为test 
test 
$ { var=notest; echo $var;} ###注意左括号和var之间要有一个空格 
notest 
$ echo $var ###父shell中的var变量的值变为了notest 
notest 
$ { var1=test1;var2=test2;echo $var1>a;echo $var2;} ###输出test1被重定向到文件a中, 
test2 ###而test2输出则仍输出到标准输出中。 
$ cat a 
test1 
$ { var1=test1;var2=test2;echo $var1;echo $var2;}>a ###括号内命令的标准输出全部被重定向到文件a中
$ cat a 
test1 
test2

变量

1、shell中0,1等变量

  • $$:shell本身的PID
  • $?:shell最后运行的命令的结束代码
  • $*:所有参数列表,如果使用”“括起来的话,会以”12 …$n”形式输出
  • $@:所有参数列表,如果使用”“括起来的话,会以”12” … “$n”形式输出**
  • $#:添加到shell的参数个数
  • $0:shell本身文件名
  • 1 n:添加到shell的各个参数值

@在不加引号的时候,都可以表示一个参数数组;而在加了引号之后,”""@”依然表示一个参数数组

${var%pattern},表示从变量$var的结尾删除最短匹配pattern的子串

${0%/*}表示删除从变量0/0是这个目录/home/john/source 那么就是把”/source”截取掉,剩下/home/john,一般用来获取当前执行脚本的目录

2、脚本变量和函数变量

  • shell中脚本定义的变量是global的,其作用域是从被定义的地方开始的,到shell结束或是被显示删除的地方为止。
#!/bin/bash
#define the function ltx_func
ltx_func()
{
   echo $v1
   #modify the variable v1
   v1=200 
}
#define the variable v1
v1=100
#call the function ltx_func
ltx_func
echo $v1

运行结果如下:

100
200

脚本变量v1的作用域从被定义的地方开始,到shell结束。调用ltx_func在变量v1的作用域内,所以能够访问并修改v1

  • 函数定义的local变量
#!/bin/bash
#define the function ltx_func
ltx_func()
{
   #define the local variable v2
   local v2=200 
}
#call the function ltx_func
ltx_func
echo $v2

运行结果如下:

(空)

函数变量v2显示定义为local,其作用域局限于函数内。打印命令在函数外,不在变量v2的作用域内。

  • 函数参数是local变量
#!/bin/bash
#define the function ltx_func
ltx_func()
{
   echo "param 1: $1"
}
#call the function ltx_func
ltx_func 100

运行结果如下:

100

函数参数是local的,通过位置变量$1来访问

  • 如果同名,shell函数定义的local变量会屏蔽脚本定义的global变量
#!/bin/bash
#define the function ltx_func
ltx_func()
{
   echo $v1
   #define the local variable v1
   local v1=200 
   echo $v1
}
#define the global variable v1
v1=100 
#call the function ltx_func
ltx_func
echo $v1

运行结果如下:

100
200
100

global变量v1的作用域从被定义的地方开始,到shell结束。在函数内又定义了local变量v1,同名local变量v1会覆盖globa变量v1。退出函数后,函数内定义的local变量v1已经消失,访问的是global变量。

算数运算

expr

expr命令是一款表达式计算工具,使用它完成表达式的求值操作。

expr常用运算符:

  • 加法运算:+
  • 减法运算:-
  • 乘法运算:\*
  • 除法运算:/
  • 求摸(取余)运算:%

示例:

$expr 9 + 8 - 7 \* 6 / 5 + \( 4 - 3 \) \* 2
11

expr同时还可以对字符串进行操作:
- match 字符串 表达式等于”字符串 :表达式”
- substr 字符串 偏移量 长度替换字符串的子串,偏移的数值从 1 起计
- index 字符串 字符在字符串中发现字符的地方建立下标,或者标0
- length 字符串字符串的长度

bc

上面我们介绍的expr之支持整数运算,但对于浮点运算就无能为力了,而且expr不能进行指数运算,而都有bc这些都不再话下。

参数:

  • -i 强制交互模式;
  • -l 使用bc的内置库,bc里有一些数学库,对三角计算等非常实用;
  • -q 进入bc交互模式时不再输出版本等多余的信息。

特殊变量:

ibase,obase 用于进制转换,ibase是输入的进制,obase是输出的进制,默认是十进制;

scale 小数保留位数,默认保留0位。

交互模式:在shell命令行直接输入bc及能进入bc语言的交互模式。
非交互模式:与echo方法一起使用。

$echo "scale=5;9+8-7*6/5^2"|bc
15.32000

$echo "ibase=16;obase=2;ABC"|bc
101010111100

小技巧:可以使用gdb来进行10进制转成16进制,print /x [num]

(( )) 和 [ ]

这两个在shell中比较常见,这两个和expr命令有些类似,也是用于整数计算。

这两个对与expr的优点是:运算符号全部不需要转义

$echo $(( 2 + 5 ))
7

$echo $(( 2 * 5 ))
10

$echo $[ 2 % 5 ]
2

$echo $[ 2 * 5 ]
10

执行多个命令

使用;

连续不中断执行命令,中间出现错误并不会中断后面命令,例如:

mkdir test; mkdir test; rmdir test;

虽然第二个命令会出错,但不会影响后面的删除目录命令

使用&&

使用&&分割的命令,如果没有错误会一直执行下去,出现错误会立即中止,例如:

mkdir test && mkdir test && rmdir test

这里在第二个命令处就终止了

使用||

使用||分隔的命令,如果有错误就一直执行下去,直到一次正确的执行就立即终止,例如:

mkdir test || mkdir test || rmdir test
mkdir test || mkdir test || rmdir test || mkdir test

第一次执行第一条指令就正确,后面的不执行

第二次执行前两条都错误,直到最后一条才正确,最后一条不再执行

多个命令构成一个数组,然后批量执行

1、(命令1;命令2;命令3)

其中()会开启一个子Shell环境来执行括号中的命令

2、{ 命令1;命令2;命令3 }

这里要注意的就是{的右边必须要有一个空格,}的左边也需要有一个空格 。和上面的方法不同的是,该方法是把批命令放在现行的shell中执行,而不是子shell中执行。

grep

基本命令

grep在一个或多个文件中查找与模式字符串(pattern)匹配的行,并将搜索的结果打印出来,不会修改原文件内容。
使用grep 命令的语法为:
grep [option] pattern [file(s)]

常用选项

  • -a 不要忽略二进制数据。
  • -c 计算符合范本样式的列数。
  • -n 在显示符合范本样式的那一列之前,标示出该列的编号。
  • -v 反转查找。

-A-B-选项详解

-A可以理解为显示查找到的行之后,还会显示之后的一行或是多行(after)

-B可以理解为显示查找到的行之后,还会显示之前的一行或是多行(before)

显示之后一行:
grep -A1 keyword filename

显示之前一行:
grep -B1 keyword filename

显示之前和之后一行
grep -1 keyword filename

正则表达式

使用[]搜索集合字符

[chainyang@DSNO_DP_PD_2 ~/small_program]$ grep '[ae]st' test.txt --color=auto
past
test
best

可以用^符号做[]内的前缀,表示除[]内的字符之外的字符。

而如果^符号不再[]内,那么就可以用来表示开头,$表示结尾。

搜索以小写字母开头的行

grep -n '^[a-z]' regular_express.txt 

搜索开头不是英文字母的行

grep -n '^[^a-zA-Z]' regular_express.txt 

Sort

sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。sort命令既可以从特定的文件,也可以从stdin中获取输入。

基本命令

sort(选项)(参数)

选项

  • -s: sort命令默认是不稳定的排序,此选项使排序结果稳定;
  • -b:忽略每行前面开始出的空格字符;
  • -c:检查文件是否已经按照顺序排序;
  • -d:排序时,处理英文字母、数字及空格字符外,忽略其他的字符;
  • -f:排序时,将小写字母视为大写字母;
  • -i:排序时,除了040至176之间的ASCII字符外,忽略其他的字符;
  • -m:将几个排序号的文件进行合并;
  • -M:将前面3个字母依照月份的缩写进行排序;
  • -n:依照数值的大小排序;
  • -o<输出文件>:将排序后的结果存入制定的文件;
  • -r:以相反的顺序来排序;
  • -t<分隔字符>:指定排序时所用的栏位分隔字符;
  • +<起始栏位>-<结束栏位>:以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
  • -k:

实例

sort将文件/文本的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

[root@mail text]# cat sort.txt 
AAA:BB:CC 
aaa:30:1.6 
ccc:50:3.3 
ddd:20:4.2 
bbb:10:2.5 
eee:40:5.4 
eee:60:5.1

# 第二列按照数字从小到大顺序排列:
[root@mail te				            
返回顶部