1.什么是shell?
用户与内核之间的一个接口。最流行和常用的: bash。
2.重定向
> 重定向到另外的文件。0,1,2对一个程序来说是最常用的三个文件描述符!
>>是把内容附加到文件的尾部而不会覆盖文件原有的内容。
这命令啥意思?
#kill -HUP 1234 >kill.std 2>kill.stderr #kill -l 1234 > kill.std 2>&1
[chengmo@centos5 shell]$
ls
test
.sh test1.sh >
/dev/null
2>&1
#将错误输出2 绑定给 正确输出 1,然后将 正确输出 发送给 /dev/null设备 这种常用
(1)shell遇到”>”操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件。不存在直接创建。 无论左边命令执行是否成功。右边文件都会变为空。很霸道的地方!
(2)“>>”操作符,判断右边文件,如果不存在,先创建。以添加方式打开文件,会分配一个文件描述符[不特别指定,默认为1,2]然后,与左边的标准输出(1)或错误输出(2) 绑定。
(3)当命令执行完,绑定文件的描述符也自动失效。0,1,2又会空闲。
(4)一条命令在执行前,先会检查输出是否正确,如果输出设备错误,将不会进行命令执行。
#ps -xo command|sort|uniq|grep -v sh|more
注意:
在一些列命令中不要使用名字相同的临时文件,因为这些文件是第一条命令被执行的时候就同时创建的,那么你只会得到一堆空白的文件。
例如:
#cat myfile.txt |more|sort>myfile.txt
你会得到一个空白的myfile.txt,因为在命令被创建的一瞬间,创建了新的空白的myfile.txt,覆盖了原本有内容的myfile.txt。
4.作为程序设计的shell
(1)交互式程序
1 $ for file in * 2 > do 3 > if grep -l POSIX $file 4 > then 5 > more $file 6 > fi 7 > done 8 posix 9 This is file with POSIX in it - treat it well 10 $
期待进一步输入的时候,提示符变成了>,而何时输入完毕由shell判断。(咋判断?)
通配符扩展(globbing):*一个字符串,?一个字符,[set]方括号中的任意一个字符,那么[^set]是取反,既匹配任何没有出现在所给的字符集中的字符。而{}允许将任何的字符串组放在一个集合中。
eg:
$ ls my_{love,wife}.name
列出文件my_love.name和my_wife.name。注意,是和!
另:上面一段代码另外的方式:
1 $ more 'grep -l POSIX *' 2 3 或: 4 $ more $(grep -l POSIX *) 5 6 这两种是等效的,推荐后一种写法,前一种写法由于带有单引号,为了避免复杂的嵌套不推荐使用。 7 8 $ grep -l POSIX * |more 9 输出有所含有POSIX字符串的文件名字,与上面的不同。
5.创建脚本和设置可执行
与交互式脚本不同的是创建可执行的脚本,这样不用每次都麻烦的输入。
1 #!/bin/bash 2 #This is command 3 4 for file in * 5 do 6 if grep -q POSIX $file 7 then 8 echo $file 9 fi 10 done 11 12 exit 0
其中#!的作用该脚本被什么程序执行,而#的作用等同于C语言中的//。
脚本程序本质上与交互式的shell输入一样,所以在其中你可以引用能通过PATH环境变量引用到的所有的Linux命令!
默认返回0表示成功,这个自然不必多说。0总是最好滴。
利用$ chmod +x first.sh把脚本设置为可执行,当然 chmod 777 first.sh或者任何包含了一个“2”的XX都可以。与PATH=$PATH:.相比更推荐$./first的方法执行脚本,尽量不要随便在环境变量中增加新的目录。
如果你想把这个脚本拷贝到其他目录,并且把管理全乡交给root用户那么见如下的代码段。
1 $ cp first.sh /usr/local/bin 2 $ chown root /usr/local/bin/first.sh 3 $ chgrp root /usr/local/bin/first.sh 4 $ chmod 755 /usr/local/bin/first.sh 5 6 另外可以 7 $ chmod u=rwx,go=rx /usr/local/bin/first.sh
6.shell的语法
(1)变量
任何一门程序设计语言首先要面对的问题就是变量,shell也不例外。
shell中的变量不用定义,就可以使用,而且默认的都是字符串形式的,如果要取值则在签名加上$符号。如果变量中含有空格,则应该用双引号将变量括起来。
1 $ string=Hello 2 $ echo $string 3 Hello 4 $ string="Hello world" 5 $ echo $string 6 Hello world 7 $ string=3+3 8 echo $string 9 3+3 10 11 一切都是字符串。 12 13 14 $ read string 15 Hi,there! 16 $ echo string 17 Hi,there! 18 19 read用来读内容
shell变量中引号的使用需要注意下,一般情况,shell中的参数就用空白符分隔,那么如果变量中本来就包含空白符那怎么办呢呢,这时候需要把变量括在双引号中。当双引号、单引号、$、/遇到一起会发生什么。
1 val = "I see" 2 3 echo $var 4 echo "$var" 5 echo '$var' 6 echo \$var 7 8 echo Enter your val 9 read val 10 11 echo '$val' now become $val 12 exit 0
这段代码将会输出
I see
I see
$var
$var
I love
环境变量:
常用的环境变量有:$HOME $PATH $PS1 $PS2 $IFS $0 $# $$
$0:脚本的名字
$#:脚本的参数个数
$$:脚本的进程号,常用来生成临时文件,如/tmp/tmpfile_$$
常用的参数变量有:$1 $2 ... $* $@
$1 $2分别是脚本程序的第一个、第二个参数。 $* 、 $@其实很像,都是在一个变量中列出所有的参数列表,唯一的区别是就分隔各个参数的字符用什么,前者和IFS的第一个字符,而后者保证参数不会挤到一起。推荐用$@,保证更加清晰和明了。
实验
#!/bin/bash val="Hi" #等号两边没有空格,注意! echo $val echo $0 echo "second para is $2" echo "first para is $1" echo "para list is $@" exit 0
程序输出如下:
$./var aa bb cc
Hi
./var
second para is bb
first para is aa
para list is aa bb cc
(2)条件
test或者[命令:
if test -f fred then ... fi 或者 if [ -f fred ] then ... fi或者if [ -f fred ];then...fi
-n string(如果string不为空,则为真)和 -z string,-eq -ne -gt -ge -lt -le !都是什么意思,很简单,猜也猜的到。
-d file 如果文件为目录-e file(-f file) 如果文件存在-f file 如果文件是一个普通文件-r file 如果文件可写-s file 如果文件大小不为0-w file 可写-x file 可执行
(3)控制结构
if condition
then
,,,
else
,,,
fi
elif作进一步检查
注意:在引用变量的时候十分推荐用“$val”的方式,即加上双引号的方式。
for val in values do statements done #!/bin/sh for foo in bar fud 43 do echo "$foo" done exit 0
(a)for循环与通配符...
1 for file in $(ls f*.sh);do 2 lpr "$file" 3 done 4 exit 0
$(command)是一个知识点,后续会有更详细的介绍。
(b)while condition do
statements
done
(c)until condition
do
...
done
until who | grep "$1" > /dev/null do sleep 60 done #循环反复执行,直到条件为真,也就是grep $1 返回真值 echo -e '\a' echo $1 has just logged in exit 0
(d)case
case val in
pattern [ | pattern] ...) statements;;
pattern [ | pattern] ...) statements;;
esac
eg:
1 #!/bin/bash 2 3 echo "Is it morning,plz tell me." 4 read awr 5 6 case "$awr" in 7 [yY]|[Yy][Ee][Ss] ) echo "Good morning";; 8 [nN]|[Nn][Oo] ) echo "Good afternoon";; 9 * ) echo "Sorry,failed" 10 esac 11 12 exit 0
为了避免过长,过复杂的条件判断和分支有了
(e)命令列表
这一样东西。
AND :s1&&s2&&s3 形似与,主析取范式。计算方法也相似。
OR: s1||s2||s3 形似或,主合取范式。
[ -f file ] && command for ture || command for false
作用类似C语言中的?:操作符。
(4)函数
shell中传递函数的方法用$*,$1等。
(5)命令
.命令比较特殊,他使一个外部命令能够在当前的shell中执行,而不是子shell环境,这样该脚本就可以改变当前的环境。
eval是shell 的内置命令,考虑如下代码段:foo=10 x=foo y=‘$’$x echo $y 和foo=10 x=foo val y=‘$’$x echo $y 第一段代码输出$foo 第二段代码输出10!
export作用是导出变量,使在父脚本中定义的变量在子脚本中可见和可以使用,一旦导出,孙脚本都可以用,呵呵。
expr是表达式求值,例如x='expr $x + 1' 同样,单引号可以被$和()组合代替,即x=$(expr $x + 1)。在同样,expr可以替换为$(())。
set的作用是为当前的shell脚本设置环境变量,l例如:
1 #!/bin/bash 2 3 echo "The date is $(date)" 4 set $(date) 5 #假定 date命令输出 2012 12 22 6 #那么set以后 该脚本的是$@就是:2012 12 22 7 echo "The month is $2"
shift左移参数,但是$0不会被覆盖,仅限于$1到无穷大,写个遍历参数的代码
1 while [ "$1"!=""];do 2 echo $1 3 shift 4 done
trap 命令 trap command signal,如此简单。command置为-表示以默认方式处理该信号,Linux中常用的信号就那么几个:HUP 1 挂起,INT 2 中断,QUIT 3 退出等等。
find命令:
eg:find / -name test -print #从根目录开始 搜索名字为test的文件 并把它打印出来。清晰 简单明了。
find命令的格式是:find [path] [option] [test] [action] ,路径部分很好理解,甚至可以同时指定多个目录。选项部分常用的有:-depth,-mount等。
测试部分MS是需要重点掌握的,-type c,-name pattern,-atime N,-mtime N,-newer otherfile,-user usrname 等等。!和-not,-a和-and,-o和-or是一样一样的。
注意在使用条件组合的时候需要括号来设置优先级,而括号在shell中又有特殊的含义,所以你必须用转移符号/来保证(和)不会被shell给处理了,eg:
find . /(-name "_*" -a -newer hahaha/) -type f -print 该命名的作用是在当前目录下查找名字以下划线开头并且比hahaha更新的 并且文件类型为普通文件,然后将它打印出来。
在find命令的最后加上-exec或者-ok你会感觉到这是神器,不过感觉有点像管道,但是又不一样好像。{}是魔术串,恩 魔术串,就是当前获取到的文件的全名,咋怎么踩刹车,\;。eg:
find .-name Iloveyou -type f -exec ls -al {} \:
grep命令:
find在文件系统中搜索文件,而grep在文件中搜索字符串,懂,亲?用exec将find的结果传递给grep,太棒了!
grep [options] PATTERN [FILES] 常用的选项:-c 输出数目,-E 启用扩展表达式,-h 取消每个输出行的普通前缀?? -i 忽略大小写 -l 只列出包含匹配行的文件名,而不输出真正的匹配行。-v 取反!(这个似乎常用!)
正则表达式:^ 表示行的开头,$表示行的结尾,.表示任意一个单个字符,[]表示一个匹配的范围。\提供了转义序列。其中[]还有很多特殊匹配模式。
eg:查找以字符e结尾的行
grep $e word.txt
eg:查找包含以字符a结尾的单词的行
grep a[[:blank:]] word.txt
eg:查找包含以TH开头的由3个字符组成的单词的行
grep TH.[[:blank:]] word.txt
eg:查找只有10个字符长并且全部由小写字母组成的单词的行
grep [[:blank:]][[:lower:]]\{10\} [[:blank:]] word.txt
可是说上说 grep -E [a-z]\{10\} word.txt
来源:https://www.cnblogs.com/unaestodo/archive/2012/12/18/2736022.html