<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    so true

    心懷未來,開創(chuàng)未來!
    隨筆 - 160, 文章 - 0, 評(píng)論 - 40, 引用 - 0
    數(shù)據(jù)加載中……

    Shell編程積累

    ls -lr反向排序結(jié)果
    ==============================
    ls ${PATH//:/\ } | grep <searchword>
    ==============================
    echo $RANDOM
    ==============================
    [[ $# -ne 3 ]] && {echo "Usage: ${0##.*/} <param>"; exit 1}
    ==============================
    awk '/'$VAR'/{print $0}' file
    ==============================
    #得到絕對(duì)路徑
    bin=`dirname "$0"`
    bin=`cd "$bin"; pwd`
    ==============================
    echo $[23*34] <==> echo $((23*34))
    ==============================
    echo $[7#23] #7是底,23是在這個(gè)底上的數(shù)字,因此最終的結(jié)果為17
    ==============================
    echo ${!P*} #列出當(dāng)前變量中,所有以P開頭的變量的名稱
    ==============================
    shell的處理過程:alias la='ls -A'->{1..100}->~admin->$PATH->$(ls)->$((23*34))->rm a*o?[a-zA-Z]*
    ==============================
    #下面這種處理方式等同于for f in "$(ls)",但是可以應(yīng)對(duì)文件名中有空格的情況,而for f in "$(ls)"則不行。
    [ $# -eq 0 ] && ls | while read f
    do
        ll-2.sh "$f"
    done
    ==============================
    可以在一行內(nèi)定義一個(gè)函數(shù),寫在shell腳本里可以,還可以直接寫在命令行上,比如:
    root@pc1:~#testfunc(){ echo "$# parameters;echo "$@";}
    而且,如果你在命令行直接這么定義的,你想查看該函數(shù)的內(nèi)容時(shí),可以用type testfunc,你會(huì)看到:
    testfunc is a function
    testfunc ()
    {
        echo "$# params";
        IFS=;
        echo "$*"
    }
    需要特別注意的是:{和echo之間的那個(gè)空格,其他地方有沒有空格無所謂,但是這個(gè)空格如果沒有的話,是必然會(huì)出錯(cuò)的;還有個(gè)地方是}前面那條命令的;必須有,否則也會(huì)有問題;最后,還需要提醒的是,如果你不是寫在一行內(nèi),那么}前的;不必有,{后的空格也不必有。
    ===============================
    對(duì)$*和$@作些說明:
    其實(shí)要分四種情況:$*, $@, "$*", "$@"
    對(duì)于前兩種情況,都等同于$1 $2 $3 ...,如果某個(gè)參數(shù)內(nèi)有了空格或者換行(不要覺得不可能,參數(shù)中是可以有換行符的,下面就有例子),比如a "b c" d,那么替換后的結(jié)果是a b c d,看上去就是四個(gè)參數(shù)了;
    對(duì)于"$@",等同于"$1" "$2" "$3" ...,這下就不必?fù)?dān)心參數(shù)中有空格或者換行符號(hào)了;
    對(duì)于"$*",還要受到IFS的影響,其實(shí)是IFS中的第一個(gè)字符的影響,假定IFS中第一個(gè)字符是|的話,那么替換后的結(jié)果是"$1|$2|$3...";這里對(duì)IFS還得作下說明,如果 IFS 為空,則沒有間隔空格。IFS 的默認(rèn)值是空白、制表符和換行符。如果沒有設(shè)置 IFS,則使用空白作為分隔符(僅對(duì)默認(rèn) IFS 而言),這里特別提到的是,如果你想把參數(shù)都串接起來,那么必須得顯示設(shè)置IFS=''或者IFS=""或者IFS=即可。
    下面給出一個(gè)驗(yàn)證上述描述的超級(jí)牛b的例子:
    [ian@pinguino ~]$ type testfunc2
    testfunc2 is a function
    testfunc2 ()
    {
        echo "$# parameters";
        echo Using '$*';
        for p in $*;
        do
            echo "[$p]";
        done;
        echo Using '"$*"';
        for p in "$*";
        do
            echo "[$p]";
        done;
        echo Using '$@';
        for p in $@;
        do
            echo "[$p]";
        done;
        echo Using '"$@"';
        for p in "$@";
        do
            echo "[$p]";
        done
    }

    [ian@pinguino ~]$ IFS="|${IFS}" testfunc2 abc "a bc" "1 2
    > 3"
    3 parameters
    Using $*
    [abc]
    [a]
    [bc]
    [1]
    [2]
    [3]
    Using "$*"
    [abc|a bc|1 2
    3]
    Using $@
    [abc]
    [a]
    [bc]
    [1]
    [2]
    [3]
    Using "$@"
    [abc]
    [a bc]
    [1 2
    3]
    看到參數(shù)中使用換行符號(hào)了吧,哈哈。
    ===============================
    函數(shù)返回值return 0~255必須為一個(gè)整數(shù),而且范圍只能是0~255,如果大于255,那么會(huì)返回$((x%256)),而且不能返回負(fù)數(shù),但是允許你寫負(fù)數(shù),負(fù)數(shù)會(huì)被強(qiáng)制轉(zhuǎn)換成整數(shù)。
    ===============================
    #!/bin/sh會(huì)提供系統(tǒng)默認(rèn)的shell解釋器,會(huì)帶來一些想不到的異常情況,建議都使用#!/bin/bash,在bash中定義函數(shù)時(shí)function關(guān)鍵字是可選的。
    ===============================
    #!/bin/bash

    showopts () {
      while getopts ":pq:" optname
        do
          case "$optname" in
            "p")
              echo "Option $optname is specified"
              ;;
            "q")
              echo "Option $optname has value $OPTARG"
              ;;
            "?")
              echo "Unknown option $OPTARG"
              ;;
            ":")
              echo "No argument value for option $OPTARG"
              ;;
            *)
            # Should not occur
              echo "Unknown error while processing options"
              ;;
          esac
        done
      return $OPTIND
    }

    showargs () {
      for p in "$@"
        do
          echo "[$p]"
        done
    }

    optinfo=$(showopts "$@")
    argstart=$?
    arginfo=$(showargs "${@:$argstart}")
    echo "Arguments are:"
    echo "$arginfo"
    echo "Options are:"
    echo "$optinfo"

     getopts 命令使用了兩個(gè)預(yù)先確定的變量。OPTIND 變量開始被設(shè)為 1。之后它包含待處理的下一個(gè)參數(shù)的索引。如果找到一個(gè)選項(xiàng),則 getopts 命令返回 true,因此常見的選項(xiàng)處理范例使用帶 case 語句的 while 循環(huán),本例中就是如此。getopts 的第一個(gè)參數(shù)是一列要識(shí)別的選項(xiàng)字母,在本例中是 p 和 r。選項(xiàng)字母后的冒號(hào) (:) 表示該選項(xiàng)需要一個(gè)值;例如,-f 選項(xiàng)可能用于表示文件名,tar 命令中就是如此。此例中的前導(dǎo)冒號(hào)告訴 getopts 保持靜默(silent)并抑制正常的錯(cuò)誤消息,因?yàn)榇四_本將提供它自己的錯(cuò)誤處理。

    此例中的第二個(gè)參數(shù) optname 是一個(gè)變量名,該變量將接收找到選項(xiàng)的名稱。如果預(yù)期某個(gè)選項(xiàng)應(yīng)該擁有一個(gè)值,而且目前存在該值,則會(huì)把該值放入 OPTARG 變量中。在靜默模式下,可能出現(xiàn)以下兩種錯(cuò)誤情況。

       1. 如果發(fā)現(xiàn)不能識(shí)別的選項(xiàng),則 optname 將包含一個(gè) ? 而 OPTARG 將包含該未知選項(xiàng)。
       2. 如果發(fā)現(xiàn)一個(gè)選項(xiàng)需要值,但是找不到這個(gè)值,則 optname 將包含一個(gè) : 而 OPTARG 將包含丟失參數(shù)的選項(xiàng)的名稱。

    如果不是在靜默模式,則這些錯(cuò)誤將導(dǎo)致一條診斷錯(cuò)誤消息而 OPTARG 不會(huì)被設(shè)置。腳本可能在 optname 中使用 ? 或 : 值來檢測(cè)錯(cuò)誤(也可能處理錯(cuò)誤)。
    此外,getopts ":pq:" optname后面還可以配置上可選的getopts ":pq:" optname "$@"

    [ian@pinguino ~]$ ./testargs.sh -p -q qoptval abc "def ghi"
    Arguments are:
    [abc]
    [def ghi]
    Options are:
    Option p is specified
    Option q has value qoptval
    [ian@pinguino ~]$ ./testargs.sh -q qoptval -p -r abc "def ghi"
    Arguments are:
    [abc]
    [def ghi]
    Options are:
    Option q has value qoptval
    Option p is specified
    Unknown option r
    [ian@pinguino ~]$ ./testargs.sh "def ghi"
    Arguments are:
    [def ghi]
    Options are:
    ===============================
    父shell設(shè)置的alias是不能傳到子shell中的,但是在shell script中依然可以使用alias,不過要自己手動(dòng)設(shè)定了,然后還要注意在腳本中顯示開啟alias的使用,即 shopt -s expand_aliases;有時(shí)候會(huì)希望alias能帶參數(shù)就好了,其實(shí)可以用函數(shù)代替即可,在.bashrc中增加:cpdev1(){ [ $# -eq 1 ] && scp $1 yanbin@dev1.asc.cnz.alimama.com: ; },具體啥意思,自己去琢磨吧。
    ===============================
    while [ "${i:-1}" -lt 30 ];do a="-"${a:="-"};((i++));done && echo $a
    知識(shí)點(diǎn):while的條件,不新建變量還能正常使用,while是個(gè)整體,可以有返回值,可以重定向其輸出
    ===============================
    如果想實(shí)現(xiàn)對(duì)shell變量的二次解析,那么可以用eval完成,例如:eval cd "\"\$$#\""
    ===============================
    for var in "$@"; <==> for var;
    ===============================
    在shell總一般extglob都是開著的,你可以用shopt查看一下,如果沒開你可以用shopt -s extglob設(shè)置一下,在這個(gè)選項(xiàng)打開的狀態(tài)下,我們可以使用一些擴(kuò)展的glob選項(xiàng),在shell中是這么使用的:
    ?(pattern-list)Matches zero or one occurrence of the given patterns
    *(pattern-list)Matches zero or more occurrences of the given patterns
    +(pattern-list)Matches one or more occurrences of the given patterns
    @(pattern-list)Matches one of the given patterns
    !(pattern-list)Matches anything except one of the given patterns
    ===============================
    find . -regextype posix-extended -regex '.*\.(h|cpp)'
    ===============================
    findc(){ [ $# -eq 1 ] && compgen -c | grep --color=auto -i $1; }
    ===============================
    在.bashrc中添加:export PS1='\[\e[1;32;40m\]\u@\h:\w\$ '達(dá)到的效果:綠色高亮顯示,且折行時(shí)不會(huì)在同一行,如果去掉\[和\]則會(huì)在同一行折行。
    本人目前在用的一個(gè)PS1是:export PS1='\[\e[0;35m\]>>>>[\[\e[0;33m\]\t\[\e[0;35m\]][\[\e[0;31m\]\u@\h\[\e[0;35m\]:\[\e[0;33m\]\[\e[0;34m\]\w\[\e[0;35m\]]\n\[\e[1;$((31+3*!$?))m\]\$ \[\e[0;32m\]' ,這個(gè)PS1會(huì)換行,而且新行的開始部分($或者#)會(huì)顯示紅色高亮(上次的命令執(zhí)行失敗)或者藍(lán)色高亮(上次的命令執(zhí)行正常)。
    對(duì)于配色,可以參考:
       前景             背景              顏色
       ---------------------------------------
       30                40               黑色
       31                41               紅色
       32                42               綠色
       33                43               黃色
       34                44               藍(lán)色
       35                45               紫紅色
       36                46               青藍(lán)色
       37                47               白色

       代碼              意義
       -------------------------
       0                 OFF
       1                 高亮顯示
       4                 underline
       5                 閃爍
       7                 反白顯示
       8                 不可見
    此外,我在ubuntu上設(shè)置了上述PS1之后,當(dāng)我在終端里打開vi再關(guān)閉vi之后,發(fā)現(xiàn)命令行出現(xiàn)了亂碼,此時(shí)輸入reset即可恢復(fù)正常,此后再使用vi將不再出現(xiàn)亂碼,不過每次都這么搞一通實(shí)在是不爽,不知道在其他發(fā)行版上會(huì)不會(huì)有這個(gè)問題。
    現(xiàn)在終于解決了這個(gè)問題,有兩種方法,一種可以在虛擬終端的title設(shè)置中給原先的終端二字前后分別添加一個(gè)英文空格即可;另一種方法是重新設(shè)置PS1為\[\e]0;\u@\h: \w\a\]\[\e[1;31m\]\u\[\e[1;32m\]@\h\[\e[1;31m\]:\[\e[1;32m\]\w\[\e[1;31m\]\$ \[\e[0m\]
    ==========================
    echo "export LS_COLORS='$LS_COLORS'" >> .bashrc之后打開.bashrc,將di=01;34改為di=01;33即可使得目錄以黃色顯示
    ==========================
    shell腳本調(diào)試,可以先設(shè)置
    export PS4='+{$LINENO:${FUNCNAME[0]}} ',再用sh -x來執(zhí)行腳本,即可在+號(hào)后面打印行號(hào)和函數(shù)名;使用trap  <cmd> DEBUG/ERR/EXIST可以分別在執(zhí)行每一行前/某個(gè)命令返回值不為0時(shí)/函數(shù)或程序退出時(shí)執(zhí)行cmd;可以在腳本里面的腳本段落前后分別用sh -x和sh +x來使得只有該段落的內(nèi)容執(zhí)行sh -x;可以通過變量DEBUG作為開關(guān)來統(tǒng)一控制調(diào)試與否,當(dāng)然需要有個(gè)函數(shù),比如也叫做DEBUG的話,那這個(gè)函數(shù)的定義大概為:DEBUG() { [ "$DEBUG" = "true" ] && $@ ; },然后你就可以肆無忌憚的DEBUG echo $a,$b或者在一段落前后分別加上DEBUG set -x和DEBUG set +x來進(jìn)行控制了;還可以使用類似于Gdb調(diào)試的bash調(diào)試工具bashdb,官網(wǎng)地址為:http://bashdb.sourceforge.net/;上述總結(jié)來自于http://www.ibm.com/developerworks/cn/linux/l-cn-shell-debug/index.html
    ============================
    export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "可以讓history顯示出執(zhí)行的時(shí)間
    ============================
    date -d "1970-01-01 0:0:0 UTC `date +%s` sec" +'%F %T' 可以將時(shí)間戳轉(zhuǎn)換為指定的時(shí)間表示形式
    用date -d @1313418365 +%F\ %T也可以實(shí)現(xiàn)將時(shí)間戳轉(zhuǎn)換為指定的時(shí)間格式
    ============================
    find . \( -path './rrds*' -o -path './bash*' \) -prune -o -maxdepth 3 -name '*m*' -printf '%f\n'
    該命令實(shí)現(xiàn)的功能是查找當(dāng)前目錄下,除了rrds*和bash*文件夾之外的名字中含有m字符的且深度不超過3層的, 將符合上述條件的目錄或文件名打印出來, 不打印全部路徑, 只打印文件名或目錄名. 寫該命令時(shí)需要注意的幾點(diǎn):\(和-path之間以及\)之前都必須有空格;針對(duì)path或name定義它們需要符合的pattern時(shí)必須要./開頭或者*開頭,因?yàn)檫@里的匹配都是全匹配,而不是包含即可的意思. 對(duì)該命令的幾點(diǎn)解釋:find查找文件名或目錄名(其實(shí)目錄也是文件)符合pattern所有項(xiàng), 如果只是中間路徑中含有pattern, 并不能保證該目錄下的所有文件都能和pattern匹配,因?yàn)槠ヅ浒l(fā)生在整個(gè)路徑的最后,也就是文件名或目錄名上;prune本意為刪除或砍掉的意思,基本上可以理解為和print恰恰相反即可,它們都是action,find命令其實(shí)類似于一個(gè)復(fù)合的if語句, action前面的默認(rèn)連接是使用-a(即and的意思, 類似于我們常見的command1 && command2 || command3中的&&的作用), 當(dāng)然也可以顯示的指定-o(即or的意思, 類似于||的作用), 既然談到了and和or,那么自然就有not了,在find命令里,not是!,舉個(gè)例子就清楚了:find . ! -name '*.sh'會(huì)找到所有不是以.sh結(jié)尾的文件, 此外還有就是通過\(和\)能夠把一些復(fù)合起來的條件作為一個(gè)整體, 因此對(duì)于該條命令, 執(zhí)行過程是這樣的, if ( -path './rrds*' && -path './bash*' ); then -prune else { if (-maxdepth 3 && -name '*m*' ); then -printf '%f\n' fi } fi
    此外對(duì)于find命令, 最常用的幾個(gè)參數(shù)是 -type和-name,其實(shí)還有-iname(忽略大小寫的匹配), 還有-regex和-iregex,注意-name只是用基本的shell的pattern,即*,?,[]三種, 如果真想用正則來匹配,還是用-regex吧; 此外對(duì)于find最神奇的莫過于-exec或者-ok或者xargs了,這里給出兩個(gè)例子即可:
    find . -name '*my*' -exec rm '{}' \;   <==>  find . -name '*my*' | xargs rm
    find. -name '*my*' -exec cp '{}' ~ \;   <==> find . -name '*my*' | xargs -i cp '{}' ~
    對(duì)于rm這種單參數(shù)的命令, find找到的結(jié)果直接會(huì)塞給rm的; 對(duì)于cp這種雙參數(shù)的命令, 可以用'{}'這個(gè)東西來代表find找到的部分, 但對(duì)于xargs中需要注意使用-i參數(shù), 該參數(shù)其實(shí)和-I參數(shù)作用是一樣的,但是特別之處在于當(dāng)不指定replace-str時(shí), -i這個(gè)參數(shù)會(huì)把{}作為replace-str, 因此使用-i就用經(jīng)管道|過來的標(biāo)準(zhǔn)輸入去替換{},因此cp命令就生效了.
    ================
    注釋大段shell腳本的方法:
    :||:<<\{{
    ...
    {{
    這里對(duì)here document也多少作些討論:該文檔其實(shí)是個(gè)臨時(shí)文檔,被生成到/tmp目錄下,你用命令bash -c 'lsof -a -p $$ -d0' <<EOF
    EOF就可以很清楚的看到這一點(diǎn);該臨時(shí)文檔為交互式shell腳本或者可執(zhí)行程序提供輸入,最典型的是為cat和ed這樣的命令feed輸入;最典型的應(yīng)用是在shell中通過cat<<來大段輸出文本, 還有一些比較巧妙的用法,比如為腳本中的函數(shù)塞入數(shù)據(jù)(注意不是為函數(shù)塞入?yún)?shù), 而是當(dāng)函數(shù)中有類似于read這樣的命令時(shí)通過here文檔來feed給它), 在比如為變量賦值variable=$(cat <<SETVAR
    This variable
    runs over multiple lines.
    SETVAR)
    再比如
    vi $TARGETFILE <<\EOF
    i
    This is line 1 of the example file.
    This is line 2 of the example file.
    ^[
    ZZ
    EOF
    here document自身所特有的幾點(diǎn)包括:
    1.用<<-代替<<可以使內(nèi)容中的leading tabs被忽略,對(duì)leading spaces無效
    2.用’HERE’, “HERE”, \HERE代替<<后面的HERE,可以使內(nèi)容中變量不被替換,諸如$HOME
    3.如果只希望輸入一行數(shù)據(jù),可以用<<<即可,例如cat <<<'hello world' (說到這里, 還真覺得蠻有意思的,一個(gè)<表示0號(hào)標(biāo)準(zhǔn)輸入; 兩個(gè)<<表示here document的臨時(shí)性輸入;三個(gè)<<<表示單行的here document輸入)
    更多詳細(xì)例子,可以參考:http://tldp.org/LDP/abs/html/here-docs.html
    ===============
    對(duì)于cat這種可以接受標(biāo)準(zhǔn)輸出或者標(biāo)準(zhǔn)輸入流的程序來說, 可以通過一個(gè)-來承載送過來的流, 大致可分為通過管道|過來的標(biāo)準(zhǔn)輸出流和通過<送進(jìn)來的標(biāo)準(zhǔn)輸入流, 通過這樣一個(gè)例子就可以看出ls | cat - t.C - -   < t.sh    <<<'single here document'   <<{{
    multiple
    here
    document
    {{
    結(jié)果只是<<發(fā)揮作用了, 它們的優(yōu)先級(jí)別是: <<最高, <<<次之, < 排第三, | 排第四
    這樣就可以利用該特性為某t.C這樣的文檔添加頁眉和頁腳了:
    頁眉: cat - t.C <<<'header'
    頁腳: cat t.C - <<<'footer'
    =======================================
    在腳本中,對(duì)于那些腳本依賴的變量,如果沒定義的話就不希望繼續(xù)執(zhí)行腳本,那么可以使用:
    set -u
    使用了那些你關(guān)注的變量的代碼段
    set +u
    這樣就可以保證腳本在執(zhí)行過程中沒有發(fā)現(xiàn)這些變量時(shí)就自動(dòng)報(bào)錯(cuò)退出
    ==========================================
    按照字符串的長(zhǎng)度進(jìn)行排序:
    #! /bin/sh
    awk 'BEGIN { FS=RS } { print length, $0}' $1 |
    sort -k 1n,1 |
    sed 's/^[0-9][0-9]* //' | tee $1 >/de
    ==========================================
    有關(guān)shell腳本的第一行,這一行可不是隨便寫的,是有講究的,首先要從這一行中提取出的是一個(gè)可執(zhí)行程序的全路徑,比需要全路徑,在#!后面可以跟空格;其次,會(huì)為這個(gè)命令要么附加一個(gè)選項(xiàng),要么附加一個(gè)參數(shù),記住,有且只能有一個(gè),而且是option和arg二選一,如果有多個(gè)參數(shù),其實(shí)可以合并,舉個(gè)例子,比如ls,可以把-a和-f合并為-af,因此在這條規(guī)則下:#!/usr/bin/env sed -f就不能work了,因?yàn)閟ed本身就已經(jīng)是env的一個(gè)arg了,其實(shí)在這種情況下,系統(tǒng)會(huì)認(rèn)為'sed -f'整體為一個(gè)arg,系統(tǒng)判斷你指定的究竟是一個(gè)arg還是一個(gè)option的依據(jù)就是:是否以-開頭。
    =============================================
    cd ~1 與cd ~-1代表cd到dirs命令列表中左數(shù)/右數(shù)第1個(gè)目錄(從0開始計(jì)數(shù)); 注意這種用法并不會(huì)與pushd沖突, 因?yàn)閜ushd會(huì)對(duì)dirs列表進(jìn)行rotate(一定要好好理解這個(gè)單詞的含義, 它相當(dāng)于把dirs的結(jié)果看作是一個(gè)round robin的環(huán)狀結(jié)構(gòu), pushd要更改的就是從這個(gè)環(huán)上的哪個(gè)地方找到隊(duì)首,然后順時(shí)針就可以找到其他的元素了)操作, 舉個(gè)例子: 假如dirs的結(jié)果為: ~    /usr     /etc    /tmp四個(gè)目錄,那么cd ~1后的結(jié)果是/usr /usr /etc /tmp; cd ~-1的結(jié)果是/etc /usr /etc /tmp; pushd +1的結(jié)果為: /usr /etc /tmp ~; pushd -1的結(jié)果為: /etc /tmp ~ /usr
    =============================================
    查看bash內(nèi)建命令的help內(nèi)容,可以用help ulimit,不過這樣得到的信息不全面,全面的信息可以在man builtins里面找到;
    ========================================
    echo -e 'a\tb'和echo $'a\tb'的結(jié)果一樣,$'string'形式的字符串會(huì)被特殊處理,字符串會(huì)被展開,并像c語言那樣將反斜杠及緊跟的字符進(jìn)行替換,擴(kuò)展后的結(jié)果將被單引號(hào)包裹,就好像美元符號(hào)一直就不存在一樣,例如$'\n' <=> $'\012' <=> $'\x0a' <=> $'\x0A';$"string"將會(huì)使得字符串被翻譯成符合當(dāng)前l(fā)ocale的語言,如果當(dāng)前l(fā)ocale是 C 或者 POSIX,美元符號(hào)會(huì)被忽略,如果字符串被翻譯并替換,替換后的字符串仍被雙引號(hào)包裹。
    =========================================
    command > out.log 2>&1  可以被command &> out.log代替,二者意義一樣,注意&和>之間不能有空格,否則&就會(huì)被認(rèn)為是要把命令放到后臺(tái)執(zhí)行,有關(guān)bash一些新增的用法可以參見:http://zh.wikipedia.org/wiki/Bash
    ============================================
    grep -e a -e b file能夠匹配到file中的行內(nèi)含有a或者b的行
    ============================================
    chvt可以替代Ctrl+Alt+Fn功能鍵;openvt可以在開滿了6個(gè)tty之后再新開tty
    ============================================
    在man或者less搜索的時(shí)候,用-i來切換大小寫是否敏感(當(dāng)最左下角顯示為:時(shí)進(jìn)行)
    =============================================
    export -f可以export函數(shù);unset -f/export -f -n可以取消函數(shù)定義;declare -f可以看到當(dāng)前bash里面所有的函數(shù)
    ==========================================================
    函數(shù)中可以再定義函數(shù),但卻不是嵌在函數(shù)里面的子函數(shù),外部依然可以隨意調(diào)用該函數(shù),也就是說和放在外面一樣,只不過看上去能感覺到:這個(gè)定義在函數(shù)A里面的函數(shù)B,應(yīng)該是專注于為函數(shù)A服務(wù)的。
    ==========================================================
    在bash里fork子shell
    #!/bin/bash
    if [ "$PROC_PID" != "$PPID" ]; then
        export PROC_PID=$$
        var="mype"
        echo "initial $var"
        declare -r var
        export var
        $0 & # child process
    else
        echo "before $var"
        var="netty5"
        echo "after $var"
    fi
    =================================================================================================
    在腳本中$@代表當(dāng)前shell腳本執(zhí)行時(shí)的所有參數(shù)或者代表傳遞到當(dāng)前函數(shù)內(nèi)部的所有參數(shù),通過shift命令,可以改變$@的內(nèi)容,但是$0始終代表當(dāng)前進(jìn)程的命令名字,而不是函數(shù)名字
    =================================================================================================
    getopts函數(shù)(bash builtin)的功能還是很弱的,比如要解析pq:,那么必須得這么寫命令才行:<your_command> -p -q test arg1 arg2 ...;參數(shù)之間不能斷開,而且還得必須緊跟在command的后面,當(dāng)然,getopts是解析$@,如果你用shift處理后的$@能滿足$1開始就是option,那么也行。
    ======================================================
    在linux下作各種進(jìn)制的轉(zhuǎn)化,有兩種方法比較好用:
    printf "%x\n" 2342  #該方法和c語言中的printf沒什么區(qū)別
    echo  'obase=16; 2342' | bc  #該方法很強(qiáng)大, 可以轉(zhuǎn)化為任意進(jìn)制, 比如printf不能做到的2進(jìn)制轉(zhuǎn)化
    ============================================================
    echo $content | while read line;
    do
    ...
    done
    上面這段代碼有3個(gè)問題:
    1. echo時(shí)應(yīng)該給$content添加雙引號(hào),否則content中的空格換行tab之類的東西就都丟了;
    2. 用管道會(huì)導(dǎo)致while是在一個(gè)新的子shell里, 導(dǎo)致在while中用的變量其實(shí)是新定義的, 而不是context中的;
    3. read會(huì)忽略前導(dǎo)空格, 因?yàn)閞ead會(huì)使用IFS的第一個(gè)字符作為分割符號(hào), 把當(dāng)前l(fā)ine分割為若干個(gè)word, 你用read word1 word2 word3會(huì)讀取到各個(gè)單詞, 默認(rèn)IFS的第一個(gè)字符是空格, 因此假定當(dāng)前l(fā)ine為'  a'的話, 那么會(huì)被切割為3部分(因?yàn)橛?個(gè)空格), 最后組裝的時(shí)候,  會(huì)忽略掉空單詞, 因此最后就只剩下a了.

    正確的做法是:
    IFS=
    while read line;
    do
    ...
    done < <(echo "$content")
    這里提一下<()和>()的用法, 這兩個(gè)東西都是命名管道(但這里是沒有名字的, 實(shí)則它們是借助于某一個(gè)fd來完成的), 相當(dāng)于你先mkfifo了一個(gè)命令管道xxx, 然后你echo "$content" > xxx, 同時(shí)你的read函數(shù)已經(jīng)在xxx的另一端候著了while read line; do ... done < xxx. 用<()和>()省略了建立xxx的過程.
    ==============================================================================
    tr 'a-z' 'A-Z' < t1.txt > t1.txt像這種語句,都會(huì)把t1.txt清空,其實(shí)是bash在這里做了手腳,我們都知道在bash中l(wèi)s *時(shí),其實(shí)bash會(huì)先把*擴(kuò)展為當(dāng)前所有的文件,然后再讓ls去顯示,這里也差不多,bash發(fā)現(xiàn)>時(shí),會(huì)先把該文件清空,然后再交給tr去處理,所以tr啥都不用做就完成了,而此時(shí)t1.txt就變成空文件了,要想避免這種情況發(fā)生,可以tr 'a-z' 'A-Z' < t1.txt >> t1.txt,但這樣會(huì)保留t1.txt之前的內(nèi)容,現(xiàn)在借助于<>,搞出個(gè)簡(jiǎn)單的方法:tr 'a-z' 'A-Z' < t1.txt 1<> t1.txt,這里1<>代表通過fd為1的文件進(jìn)行read and write,這樣就繞過了bash的提前解析,因此t1.txt中的內(nèi)容也被成功替換掉了。但要注意的是,同時(shí)從一個(gè)文件既讀取又寫入,而且是以管道這種流的形式來搞(正因?yàn)槭橇鞯男问剑圩x一點(diǎn)寫一點(diǎn)],所以就不會(huì)全部讀到內(nèi)存中,然后再處理,再把處理后的結(jié)果從內(nèi)存中dump到輸出文件),所以這種只對(duì)那種本位替換有效果,例如tr或者sed這種,其實(shí)說到這里,主要是為了引出<>這個(gè)符號(hào)的用法,并讓大家知道bash會(huì)先把>給解析了,其他的都不重要。
    strace是個(gè)太好太好的命令,例如strace sed -i 's/a/A/g' t1.cpp即可看到sed是使用了臨時(shí)文件進(jìn)行替換的。
    ================================================
    #!/bin/bash

    mput() {
        eval "__map_$1"__"$2"='$3'
    }

    mget() {
        eval echo '${__map_'"$1__$2"'}'
    }

    mgetall() {
        for i in $(eval echo '${!__map_'"$1"'__*}'); do
            echo -n "${i#__map_$1__*}:"
            eval echo '${'"$i"'}';
        done
    }

    mput capitals France Paris
    mput capitals Spain Madrid

    echo "$(mget capitals France)"
    mgetall capitals
    =================================================
    func () {
        local unset_x=false
        [[ "$(echo $-)" =~ x ]] || unset_x=true
        [ "false" == "$unset_x" ] && set +x
        #procedure here
        [ "false" == "$unset_x" ] && set -x
    }
    =================================================
    ulimit -c unlimited
    export PS4='+{$LINENO($(date +"%F %T")):${FUNCNAME[0]}} '
    exec 1>${0%.*}.log
    exec 2>${0%.*}.err
    mkdir -p .tmp
    export TMPDIR=.tmp
    set -x
    ====================================================
    __created_tmp_files__=""
    delete_tmp_files() {
        if [ -n "$__created_tmp_files__" ]; then
            rm -f $__created_tmp_files__
        fi
    }

    trap delete_tmp_files EXIT

    create_tmp_file() {
        local unset_x=false
        [[ "$(echo $-)" =~ x ]] || unset_x=true
        [ "false" == "$unset_x" ] && set +x
        if [ -z "$(eval "echo $"$1)" ]; then
            eval "$1=.tmp/.__${0##*/}_${LINENO}_$1_${RANDOM}__.tmp"
            rm -f $(eval "echo $"$1)
            __created_tmp_files__="$__created_tmp_files__ $(eval "echo $"$1)"
        fi
        [ "false" == "$unset_x" ] && set -x
    }
    ===================================================
    awk '
    {
        if (NF>5 || ("noresource" != $NF && "zero" != $NF && "part" != $NF && "all" != $NF)) {
            print $0 > "/dev/stderr"
        } else if ($4 ~ /^http/) {
            print $1, (4==$2 ? "y" : "n"), $4, ($5=="all" ? "y" : "n")
        } else {
            print $1, (4==$2 ? "y" : "n"), "none", ($4=="all" ? "y" : "n")
        }
    }' $2 | awk '
    BEGIN {
        pv=0;
    }
    {
        if (FILENAME==ARGV[1]) {
            sitepv[$1]=++pv;
        } else {
            r[sitepv[$1]]=$0;
        }
    }
    END {
        for (i in r) {
            print i, r[i];
        }
    }' $1 - | sort -n -k 1 | awk '
    {
        for (i=2; i<NF; ++i) {
            printf "%s ", $i
        }
        printf "%s\n", $NF
    }'
    ==========================================
    awk -v max_qps=$max_qps -v max_qps_time="$max_qps_time" -v bad_request_num=$bad_request_num '
    BEGIN {
        total_request_num=0;
        total_sum=0;
        max_value=0;
        max_value_time=0;
        min_value=0;
        min_value_time=0;
        cur_value=0;
        level8_threshold=(0 != l8 ? l8 : 3000);
        level7_threshold=(0 != l7 ? l7 : 1500);
        level6_threshold=(0 != l6 ? l6 : 1000);
        level5_threshold=(0 != l5 ? l5 : 500);
        level4_threshold=(0 != l4 ? l4 : 200);
        level3_threshold=(0 != l3 ? l3 : 100);
        level2_threshold=(0 != l2 ? l2 : 50);
        level1_threshold=(0 != l1 ? l1 : 30);
        gt_level8_threshold_num=0;
        gt_level7_threshold_num=0;
        gt_level6_threshold_num=0;
        gt_level5_threshold_num=0;
        gt_level4_threshold_num=0;
        gt_level3_threshold_num=0;
        gt_level2_threshold_num=0;
        gt_level1_threshold_num=0;
        le_level1_threshold_num=0;
    }
    1 == NR {
        cur_value=int(substr($14,4));
        max_value=min_value=cur_value;
        max_value_time=min_value_time=int(substr($1,4));
        ++total_request_num;
        total_sum += cur_value;
        next;
    }
    {
        cur_value=int(substr($14,4));
        if (cur_value > max_value) {
            max_value=cur_value;
            max_value_time=int(substr($1,4));
        } else if (cur_value < min_value) {
            min_value=cur_value;
            min_value_time=int(substr($1,4));
        }
        if (cur_value > level8_threshold) {
            ++gt_level8_threshold_num;
        } else if (cur_value > level7_threshold) {
            ++gt_level7_threshold_num;
        } else if (cur_value > level6_threshold) {
            ++gt_level6_threshold_num;
        } else if (cur_value > level5_threshold) {
            ++gt_level5_threshold_num;
        } else if (cur_value > level4_threshold) {
            ++gt_level4_threshold_num;
        } else if (cur_value > level3_threshold) {
            ++gt_level3_threshold_num;
        } else if (cur_value > level2_threshold) {
            ++gt_level2_threshold_num;
        } else if (cur_value > level1_threshold) {
            ++gt_level1_threshold_num;
        } else {
            ++le_level1_threshold_num;
        }
        ++total_request_num;
        total_sum += cur_value;
    }
    END {
        gt_level7_threshold_num += gt_level8_threshold_num;
        gt_level6_threshold_num += gt_level7_threshold_num;
        gt_level5_threshold_num += gt_level6_threshold_num;
        gt_level4_threshold_num += gt_level5_threshold_num;
        gt_level3_threshold_num += gt_level4_threshold_num;
        gt_level2_threshold_num += gt_level3_threshold_num;
        gt_level1_threshold_num += gt_level2_threshold_num;
        print total_request_num;
        printf "%d(%.2f%%)\n", bad_request_num, bad_request_num * 100 / total_request_num;
        printf "%d(occur at: %s)\n", max_qps, max_qps_time;
        cmd="date -d @"max_value_time" +\"%F %T\""; cmd | getline max_value_time_str; close(cmd);
        printf "%d ms(occur at: %s)\n", max_value, max_value_time_str;
    #   printf "%d ms(occur at: %s)\n", min_value, strftime("%F %T", min_value_time);
        printf "%.2f ms\n", total_sum / total_request_num;
        print gt_level8_threshold_num;
        print gt_level7_threshold_num;
        print gt_level6_threshold_num;
        print gt_level5_threshold_num;
        print gt_level4_threshold_num;
        print gt_level3_threshold_num;
        print gt_level2_threshold_num;
        print gt_level1_threshold_num;
        print le_level1_threshold_num;
    }' $tmp_analyse_file
    =================================================================
    awk -v threshold=1000 -v debug=n '
    BEGIN {
    }
    {
        if (FILENAME==ARGV[1]) {
            checked_css[$1]="y";
        } else if ("y" != checked_css[$1]) {
            if (n[$1] < threshold) {
                css[$1, n[$1]++] = $2;
            } else {
                k = int((rand() * threshold) % threshold);
                if("y"==debug)print "[DEBUG]over threshold:", $1, "k=", k, "old item:", css[$1, k], "new item:", $2 > "/dev/stderr";
                css[$1, k] = $2;
            }
        } else {
            if("y"==debug)print "[DEBUG]existed css:",$1 > "/dev/stderr";
        }
    }
    END {
        for (i in n) {
            if (n[i] >= threshold) {
                printf "%s\t", i;
                for (j=0; j< threshold; ++j) {
                    printf "%s ", css[i, j];
                }
                printf "\n";
            }
        }
    }' css_ok.txt -
    ========================================================================
    awk 'BEGIN {
        OFS=",";
        array[1,2]=3; array[2,3]=5; array[3,4]=8; 
        for (comb in array) {
            split(comb,sep,SUBSEP);
            print sep[1], sep[2], array[sep[1],sep[2]];
        }
    }'
    ========================================================================
    $ awk 'BEGIN{a["one"]=1;a["two"]=2;a["three"]; if("one2" in a)print a["one"]; for(i in a) print i, a[i]}'
    three 
    one 1
    two 2
    =========================================================================
    $ awk 'BEGIN{a=3;b=4; print a,b; print a, b; print a b;print a  b;}'
    3 4
    3 4
    34
    34
    ==========================================================================
    $ awk -F$'\t' 'BEGIN{OFS="\t"}{if($3 ~ /ECSHOP/)print $1,$2;}' t3.4 #否則會(huì)用空格來分隔fields,print $0不受OFS的影響
    ==========================================================================
    bash里面的大小寫轉(zhuǎn)換:
    $ a="abCdEF"
    $ echo ${a^} #process the first character
    AbCdEF
    $ echo ${a^^} #process all characters
    ABCDEF
    $ echo ${a,} #process the first character
    abCdEF
    $ echo ${a,,} #process all characters
    abcdef
    bash里的substr:
    $ a="abCdEF"
    $ echo ${a:1}
    bCdEF
    $ echo ${a:2:1}
    C
    bash里的數(shù)組操作:
    a=() #empty array
    a=(one two three) #three elements in array, with subscripts: 0 1 2
    ${#a[*]} #length of array
    ${a[*]} #all elements of array
    ${!a[*]} #all subscripts of array
    ${a[*]:2:1} #extract elements, offset index is 2, and length is 1
    ${a[*]:2} #extract elements, offset index is 2, and length is big enough to fetch all residue elements
    ${a[*]: -1} #extract last element, note that the space between : and -, by the way, ${@:3:2} will extract $3 and $4
    unset a[0] #destory the element with 0 subscript
    unset a[*] #destory array
    bash里的associated數(shù)組(即map):
    這個(gè)特性需要bash的版本>=4
    declare -A a
    $ a[one]=1
    $ a["two"]=2
    $ a[3]=three
    $ echo ${!a[*]}
    one two 3
    bash里數(shù)組元素是否存在的檢測(cè)方法:
    $ ${a[two]+:} false && echo ok || echo fail #${var+XX} will be XX if var is set, or empty; so ${a[two]+:} false will be ': false'
    ok
    $ [[ ${a[two]+set} ]] && echo ok || echo fail #${a[two]+set} will be 'set', so [[ set ]] is true;
    ok
    $ ${a[2]+:} false && echo ok || echo fail #${a[2]+:} false will be ' false'
    fail
    更多詳情可參見:http://mywiki.wooledge.org/BashFAQ/083
    bash里的復(fù)合命令(Compound Commands):
    (( expression ))用于檢測(cè)數(shù)值運(yùn)算(ARITHMETIC EVALUATION),例如
    $ (( 3+3 )) && echo ok || echo fail
    ok
    $ (( 3-3 )) && echo ok || echo fail
    fail
    也包括數(shù)值類的比較運(yùn)算符:< > >= !=等
    [[ expression ]]用于檢測(cè)字符串相關(guān)的表達(dá)式,例如 [[ hello ]], [[ -f test.dat ]], 也可用于帶BashPattern的匹配,例如[[ abc == ab* ]],或者正則字符串匹配[[ abc =~ ^ab ]]
    [ expression ]不屬于bash,因?yàn)閇其實(shí)是一個(gè)外部命令,和ls一樣
    bash里忽略大小寫的字符串比較:
    $ shopt -s nocasematch
    $ [[ aBc == abc ]] && echo ok || echo fail
    ok
    set -o會(huì)列出控制bash的所有選項(xiàng),其實(shí)還有一些其他的選項(xiàng)需要通過shopt來控制,shopt會(huì)列出全部的選項(xiàng)
    ===========================================================
    a2=99
    a1=88
    b=a2
    echo ${!a*} #list all shell variables that start with a
    a1 a2
    echo ${!b} #this express is equal to: eval 'echo $'$b
    99
    ================================================================
    !net #從歷史命令里搜索以net開頭的最近使用的一條命令
    !?net #從歷史命令里搜索包含net的最近使用的一條命令
    !:0 #上一條命令的command(類似于argv[0])
    !:^ #上一條命令的第一個(gè)參數(shù)
    !:$ #上一條命令的最后一個(gè)參數(shù)(效果等同于Alt+. ,不過Alt+.按n次,是會(huì)到倒數(shù)第n條命令里取得最后一個(gè)參數(shù)的)
    !:* #上一條命令的所有參數(shù)(效果等同于 !:^-$)
    !:2-4 #上一條命令的第2個(gè)到第4個(gè)參數(shù)
    !:2* #上一條命令從第2個(gè)參數(shù)開始(包括第2個(gè)參數(shù))以后的參數(shù)(效果等同于!:2-$)
    !:2- #上一條命令從第2個(gè)參數(shù)開始(包括第2個(gè)參數(shù))到 倒數(shù)第2個(gè)參數(shù),即省略掉最后一個(gè)參數(shù)
    ^ll^md5sum #從上一條里把第一次出現(xiàn)的ll替換為md5sum后重新執(zhí)行
    !!:gs/ll/md5sum #從上一條命令里把所有出現(xiàn)的ll都替換為md5sum(這里的語法類似于sed,/也可以用其他符號(hào)例如@來代替,g表示多次匹配)
    !! #重新執(zhí)行上一條命令(效果等同于Ctrl-p)

    posted on 2009-06-16 00:37 so true 閱讀(1749) 評(píng)論(0)  編輯  收藏 所屬分類: Linux

    主站蜘蛛池模板: 国产美女a做受大片免费| 亚洲va成无码人在线观看| 日韩一区二区a片免费观看| a色毛片免费视频| 一级做a爰片久久毛片免费陪 | 精品一区二区三区无码免费直播| 亚洲国产精品国自产拍AV| 亚洲精品高清一二区久久| 妞干网免费观看视频| 亚洲香蕉免费有线视频| 免费成人高清在线视频| 久久久久免费视频| 人妻无码中文字幕免费视频蜜桃| 亚洲日韩av无码中文| 亚洲av永久无码嘿嘿嘿| 亚洲国产精品一区二区久| 久久亚洲精精品中文字幕| 亚洲丁香色婷婷综合欲色啪| 亚洲国产婷婷香蕉久久久久久| 在线观看视频免费国语| AV片在线观看免费| 国产片AV片永久免费观看| 最近中文字幕高清免费中文字幕mv| 久久99免费视频| 久久精品国产影库免费看| 免费精品久久天干天干| 成av免费大片黄在线观看| 国产免费牲交视频免费播放| 中文字幕成人免费高清在线| 国产在线观看无码免费视频| a级毛片免费在线观看| 日韩免费无码一区二区三区| 国产成人精品日本亚洲直接 | 中文字幕免费在线看线人动作大片 | 亚洲国产综合AV在线观看| 亚洲精品中文字幕| 亚洲色无码国产精品网站可下载| 久久乐国产综合亚洲精品| 苍井空亚洲精品AA片在线播放| 国产偷国产偷亚洲清高APP| 国产亚洲精品美女久久久久|