zoukankan      html  css  js  c++  java
  • C2 shell

    1.什么是shell?

    用户与内核之间的一个接口。最流行和常用的: bash。

    2.重定向

    > 重定向到另外的文件。0,1,2对一个程序来说是最常用的三个文件描述符!

    >>是把内容附加到文件的尾部而不会覆盖文件原有的内容。

    这命令啥意思?

    #kill -HUP 1234 >kill.std 2>kill.stderr
    #kill -l 1234 > kill.std 2>&1
    第一条语句的解读:>kill.std等同于1>kill.std,标准输出1是默认的可以不写!
    第二条语句的解读:将标准错误输出2绑定到标准输出1,然后将标准输出重定向到kill.std。
    另外一个例子:
    [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)一条命令在执行前,先会检查输出是否正确,如果输出设备错误,将不会进行命令执行。

     
    3.管道
    进程同时运行并且数据在他们之间自动协调的流动。
    #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

     

     

     

     

     

     

     

     

     

     

     
     
     
  • 相关阅读:
    drop table 、delete table和truncate table的区别
    润乾报表 删除导出excel弹出框里的选项
    学习笔记: 委托解析和封装,事件及应用
    学习笔记: 特性Attribute详解,应用封装
    学习笔记: 反射应用、原理,完成扩展,emit动态代码
    学习笔记: 泛型应用、原理、协变逆变、泛型缓存
    jmeter4.x centos7部署笔记
    rabbitmq3.7.5 centos7 集群部署笔记
    rabbitmq3.8.3 centos7 安装笔记
    UVA-12436 Rip Van Winkle's Code (线段树区间更新)
  • 原文地址:https://www.cnblogs.com/unaestodo/p/2736022.html
Copyright © 2011-2022 走看看