歡迎您光臨本站 註冊首頁

Bash Use And Programming

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

鄭重聲明,這個文章不是我寫的,是我的同事——劉彬做的學習筆記.我覺得寫的太好了,但他又沒有發到網上,只好自己貼一下了.所以轉載必須帶上原作者的名字,以及本段聲明.

Bash Use And Programming

Contents

  • 1 Bash 使用
    • 1.1 按鍵綁定
    • 1.2 歷史記錄
    • 1.3 高亮
    • 1.4 Bash Completion
  • 2 Bash 編程
    • 2.1 第一行
    • 2.2 Reserved Words (保留字)
    • 2.3 Parameters (參數)
      • 2.3.1 Positional Parameters (位置參數)
      • 2.3.2 Special Parameters (特殊參數)
    • 2.4 Branches And Loops (分支與循環)
      • 2.4.1 Branches
      • 2.4.2 Loops
    • 2.5 Expansion (擴展)
      • 2.5.1 Brace Expansion (大括弧擴展)
      • 2.5.2 Tilde Expansion
      • 2.5.3 Parameter Expansion (參數擴展)
      • 2.5.4 Command Substitution (命令替換)
      • 2.5.5 Arithmetic Expansion (數學擴展)
      • 2.5.6 Process Substitution (進程替換)
      • 2.5.7 Word Splitting (單詞分割)
      • 2.5.8 Pathname Expansion (路徑擴展)
      • 2.5.9 Quote Removal (引號去除)
    • 2.6 Tips
      • 2.6.1 空字元串測試
      • 2.6.2 大小寫轉換
      • 2.6.3 隨機數
      • 2.6.4 read
      • 2.6.5 $cmd 與 eval $cmd
      • 2.6.6 local是個內建命令
      • 2.6.7 賦值語句後跟命令
      • 2.6.8 將結果打到標準輸出和錯誤輸出
      • 2.6.9 子shell
      • 2.6.10 :(){ :|: & };:
      • 2.6.11 調試

此文分享我在bash學習,使用,編程中的碰到的一些問題,以及一些體會.

1 Bash 使用

1.1 按鍵綁定

CTRL 鍵相關的快捷鍵:

  • Ctrl a - Jump to the start of the line
  • Ctrl b - Move back a char
  • Ctrl c - Terminate the command
  • Ctrl d - Delete from under the cursor
  • Ctrl e - Jump to the end of the line
  • Ctrl f - Move forward a char
  • Ctrl k - Delete to EOL
  • Ctrl l - Clear the screen
  • Ctrl r - Search the history backwards
  • Ctrl R - Search the history backwards with multi occurrence
  • Ctrl u - Delete backward from cursor // 密碼輸入錯誤的時候比較有用
  • Ctrl xx - Move between EOL and current cursor position
  • Ctrl x @ - Show possible hostname completions
  • Ctrl z - Suspend/ Stop the command
  • Ctrl h - backward-delete-char
  • Ctrl w - unix-word-rubout
  • Ctrl p - previous-history
  • Ctrl n - next-history

ALT 鍵相關的快捷鍵:

  • Alt < - Move to the first line in the history
  • Alt > - Move to the last line in the history
  • Alt ? - Show current completion list
  • Alt * - Insert all possible completions
  • Alt / - Attempt to complete filename
  • Alt . - Yank last argument to previous command
  • Alt b - Move backward
  • Alt c - Capitalize the word
  • Alt d - Delete word
  • Alt f - Move forward
  • Alt l - Make word lowercase
  • Alt n - Search the history forwards non-incremental
  • Alt p - Search the history backwards non-incremental
  • Alt t - transpose-words
  • Alt u - Make word uppercase
  • Alt back-space - Delete backward from cursor

可通過bash內鍵命令 bind 修改按鍵綁定,具體可查幫助: help bind

對於使用readline庫的程序,可修改 /etc/inputrc 或 ~/.inputrc 修改綁定關係.

ps: 使用vim的建議交換 CapsLock 與 Esc 鍵

  • X window 下用xmodmap
  • console 下用loadkeys
  • Gnome的鍵盤選項里也有’互換CapsLock、Esc”的條目. ubuntu: system->preferences->keyboard->layouts->layout options->capslock key behaivor->swap esc and capslo

我的 ~/.inputrc

   "e[A": history-search-backward   "e[B": history-search-forward   "C-p": history-search-backward   "C-n": history-search-forward      # mappings for Ctrl-left-arrow and Ctrl-right-arrow for word moving   "e[1;5C": forward-word   "e[1;5D": backward-word   "e[5C": forward-word   "e[5D": backward-word   "ee[C": forward-word   "ee[D": backward-word   

1.2 歷史記錄

   # 忽略重複的命令   export HISTCONTROL=ignoredups   # 忽略由冒號分割的這些命令   export HISTIGNORE="[   ]*:&:bg:fg:exit"   export HISTFILESIZE=1000000000   export HISTSIZE=1000000   export HISTFILE=~/.lb_bash_history   shopt -s histappend   

1.3 高亮

ls

   eval "`dircolors -b ~/.dircolors`"   alias ls='ls --color=auto'   

grep, fgrep, egrep

   export GREP_OPTIONS='--color=auto'   

man

   export LESS_TERMCAP_mb=$'E[01;31m'   export LESS_TERMCAP_md=$'E[01;31m'   export LESS_TERMCAP_me=$'E[0m'   export LESS_TERMCAP_se=$'E[0m'   export LESS_TERMCAP_so=$'E[01;44;33m'   export LESS_TERMCAP_ue=$'E[0m'   export LESS_TERMCAP_us=$'E[01;32m'   

1.4 Bash Completion

   if [ -f /etc/bash_completion ]; then       . /etc/bash_completion   fi   

中文目錄拼音補全: chsdir

介紹怎樣編寫補全腳本: An introduction to bash completion part 1 , An introduction to bash completion part 2

Bash completion for discoverer and retriever

   function _discoverer()   {       local cur prev opts       COMPREPLY=()       cur="${COMP_WORDS[COMP_CWORD]}"       prev="${COMP_WORDS[COMP_CWORD-1]}"          opts="-r --home -v --version -h --help -w --website -k --keyword -K --linksite-keyword    -c --category --related -u --userid -m --max-videos -M --max-pages    -F --linksite-fullsite -C --linksite-category --log-level"          case "$prev" in           -w | --website)           local running="youtube dailymotion myspace aol_movie metacafe msn tudou veoh yahoo youku megavideo ku6 s56 pomoho room6 pandora salloumi nicovideo myvideo tu 66stage blogspot campusist chewymovies fastpasstv freetvonline legalmovies mediateevee movie6 moviesondemand movierumor moviesdesk moviesforfree moviesister movietvonline mymovies nabolister omegatube quickss sevenscreen sidereel tvdash tvpapa watchnewmovies watchmovies watchtvsitcoms wizmovies xoxomovie live-video msn-video sogou-video bing-video-cn bing-video-com baidu-video google-video-cn google-video-com gougou-video soso-video alluc nabolister tvshack tvlinks watchmoviesfree taringa thepiratecity cinemawiki joox tvpapa familyguy freeonlineepisode moviealien tubezoom videofactor redcurtainmovies findthatshow watcheveryshow watchgossipgirl bynik watchtvsitcoms likestreaming allomovies alloshowtv diziport surfthechannel delatv estrenosonline momomesh movie2k ls2megaupload yesfilmes ninjavideo yidio casttv videosurf"              running ="youporn slutload xnxx gaywatch megaporn xvideos itsallgay tube8 tnaflix keezmovies xhamster gayforit redtube empflix pornhub jerkyourtube youporngay"              COMPREPLY=( $(compgen -W "$running" -- "$cur") )           return 0           ;;           -r | --home)           local running="$(dirname $PWD)"           COMPREPLY=( $(compgen -W "$running" -- "$cur") )           return 0           ;;           *)           ;;       esac          if [[ ("$cur" == -*) || ( ("$cur" = "") && ("$prev" != -*) ) ]] ; then           COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )       fi   }   complete -F _discoverer discoverer      function _retriever()   {       local cur prev opts       COMPREPLY=()       cur="${COMP_WORDS[COMP_CWORD]}"       prev="${COMP_WORDS[COMP_CWORD-1]}"          opts="-r --home -v --version -h --help -d --detail -D --download -k --keyid --removal --resource --log-level"       opts ="  --need-multi-clip --max-total-size --max-clip-num"          case "$prev" in           -r | --home)           local running="$(dirname $PWD)"           COMPREPLY=( $(compgen -W "$running" -- "$cur") )           return 0           ;;           *)           ;;       esac          if [[ ("$cur" == -*) ]] ; then           COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )       fi   }   complete -F _retriever retriever           

2 Bash 編程

2.1 第一行

腳本程序通常第一行以 #! 開頭指定一個腳本解釋器.如

   #!/bin/bash   #!/bin/sh   #!/usr/bin/awk -f   #!/bin/sed -f   #!/usr/bin/expect -f   #!/usr/bin/env perl   

注意 : linux 裡面,解釋器之後只能有一個參數,如有多個,也只做為一個.

例子: test.pl

   #!/usr/bin/env LC_CTYPE=zh_CN.UTF-8 perl   print "hellon"   

perl test.pl 可以正常運行,./test.pl則不會正常執行,且不會退出.

運行 ./test.pl 相當於 /usr/bin/env "LC_CTYPE=zh_CN.UTF-8

perl" ./test.pl . evn會先設置LC_CTYPE="zh_CN.UTF-8 perl"這樣一個環境變數,然後執行 ./test.pl,這就回到了最開始,於是一不斷重複這個過程,不退出.


ps: 關於腳本程序第一行的相關信息可見於:man execve

2.2 Reserved Words (保留字)

Bash 有以下保留字:

! case do done elif else esac fi for function if in select then until while { } time [[ ]]

注意:

  • time 是保留字,不是一個內建命令,跟 /usr/bin/time 有本質的區別. 區別於命令的例子: time ls >/dev/null 2>&1/usr/bin/time ls >/dev/null 2>&1
  • [[ ]] 是保留字,跟 [ ] (內建命令) 有本質的區別,不能將 [[ ]] 視為一個功能更強大的 [ ].
    • Word splitting and pathname expansion are not performed on the words between the [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed.
    • Conditional operators such as -f must be unquoted to be recognized as primaries.
    • ==, !=, =~ 右邊的字元串如被引用則進行字元串匹配,而不再是pattern match或正則匹配

ps: 可用 type 查看是否為保留字,內建命令等

2.3 Parameters (參數)

A parameter is an entity that stores values. A variable is a parameter denoted by a name.

2.3.1 Positional Parameters (位置參數)

指 $1, $2, $3 等

注意: $0, $1, .. $9 沒有問題,$10 將被解釋為 ${1}0.要使用 >= 10 的位置參數,需用 { } 括起來,如 ${15}.

2.3.2 Special Parameters (特殊參數)

From bash manual

   The shell treats several parameters specially.  These parameters may only be referenced; assignment to them is not allowed.   *      Expands  to the positional parameters, starting from one.  When the expansion occurs within double quotes, it expands to a single word with the value          of each parameter separated by the first character of the IFS special variable.  That is, "$*" is equivalent to "$1c$2c...", where  c  is  the  first          character  of  the  value  of  the IFS variable.  If IFS is unset, the parameters are separated by spaces.  If IFS is null, the parameters are joined          without intervening separators.   @      Expands to the positional parameters, starting from one.  When the expansion occurs within double quotes, each parameter expands to a separate  word.          That  is,  "$@"  is  equivalent to "$1" "$2" ...  If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined          with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word.  When  there          are no positional parameters, "$@" and $@ expand to nothing (i.e., they are removed).   #      Expands to the number of positional parameters in decimal.   ?      Expands to the exit status of the most recently executed foreground pipeline.   -      Expands  to  the  current  option  flags  as  specified upon invocation, by the set builtin command, or those set by the shell itself (such as the -i          option).   $      Expands to the process ID of the shell.  In a () subshell, it expands to the process ID of the current shell, not the subshell.   !      Expands to the process ID of the most recently executed background (asynchronous) command.   0      Expands to the name of the shell or shell script.  This is set at shell initialization.  If bash is invoked with a file of commands, $0 is set to the          name  of  that file.  If bash is started with the -c option, then $0 is set to the first argument after the string to be executed, if one is present.          Otherwise, it is set to the file name used to invoke bash, as given by argument zero.   _      At shell startup, set to the absolute pathname used to invoke the shell or shell script being executed as passed in the environment or argument list.          Subsequently,  expands to the last argument to the previous command, after expansion.  Also set to the full pathname used to invoke each command exe          cuted and placed in the environment exported to that command.  When checking mail, this parameter holds the name of the  mail  file  currently  being          checked.           

使用較多的有 $*, $@, $#, $?, $$, $!, $0

*@ 的區別,在別的地方法了是這樣.如在數組中 "${array[*]}""${array[@]}" .

2.4 Branches And Loops (分支與循環)

2.4.1 Branches

  • if list; then list; [ elif list; then list; ] ... [ else list; ] fi

    這是最常用的分支語句,通常用 [ ], [[ ]], (( )) 進行條件測試.事實上一切語句都可以用,如

       if echo "$var" | tr '[:upper:]' '[:lower:]' | grep -q 'regex expression' ; then       echo matched   fi   
  • case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac

    case 使用 pattern 匹配進行測試,變得非常好用. 如檢查一個字元串是否包含別一個字元串

       case "$1" in )       *"$2"* ) true ;;       * ) false ;;   esca           

  • &&, ||

    [ $# -ne 2 ] && exit 1[ $# -eq 2 ] || exit 1

2.4.2 Loops

  • for name [ in word ] ; do list ; done

       for host in $(<host_list) ; do ... ; done   for i in {1..100} ; do ... ; done   for f in /aaa/bbb/cc* ; do ... ; done   for v in "$@" ; do ... ; done   
  • for (( expr1 ; expr2 ; expr3 )) ; do list ; done

    跟 c/c 中 for 語義一致,好用.如

       for (( i=0; i<100; i   )) ; do ... ; done   
  • while list; do list; done

       while true ; do ...; done   while read line ; do ...; done < input_file           

  • until list; do list; done

    語義跟while相反,沒見人用過.

2.5 Expansion (擴展)

2.5.1 Brace Expansion (大括弧擴展)

   $ echo abc{d,e,f}   abcd abce abcf   $ echo {a,b,c}{d,e,f}   ad ae af bd be bf cd ce cf      $ echo {1..10}   1 2 3 4 5 6 7 8 9 10   $ echo {1..10..2}   1 3 5 7 9   

ps:

cp filename{,.bak} 好像是某個網站選出來的十大最酷的linux單行命令之一.

2.5.2 Tilde Expansion

   $ echo ~   /home/liubin   $ echo ~liubin   /home/liubin   $ echo ~tracker   /home/tracker   $ echo ~no   ~no      $ echo ~    /tmp   $ echo ~-   /home/liubin           

2.5.3 Parameter Expansion (參數擴展)

最基本的

  • $parameter
  • ${parameter}

根據parameter未定義或值為空進行操作/擴展

  • ${parameter:-word}

  • ${parameter:=word}

  • ${parameter:?word}

  • ${parameter: word}

    較為有用,可用於為輸入參數置默認值等.如

       out_file=${1:-/dev/null}   
       size=$(stat -c %s $file)   if [ ${size:-0} -lt 100 ] ; then       ...   fi   

數組相關

  • ${name[subscript]}
  • ${name[*]}
  • ${name[@]}
  • ${#name[*]}
  • ${#name[@]}
  • ${!name[*]}

  • ${!name[@]}

字元串操作

  • ${#parameter}

  • ${parameter:offset}

  • ${parameter:offset:length}

  • ${parameter#word}

  • ${parameter##word}

  • ${parameter%word}

  • ${parameter%%word}

    非常有用,如 basename 可近似於 ${path##*/} , dirname 可近似於 ${path$/*}

  • ${parameter/pattern/string}

  • ${parameter^pattern}

  • ${parameter^^pattern}

  • ${parameter,pattern}

  • ${parameter,,pattern}

    上面四個大小寫轉換的應該是在 bash 4.0 中引入的.寫入腳本中要慎重.

另外

  • ${!prefix*}
  • ${!prefix@}

2.5.4 Command Substitution (命令替換)

$(command) or `command`

會去掉的newline,但中間的會保留.

var=$(<file) 跟var=$(cat file) 是相同的,但要快.

  1. ``與$()處理 '' 的方式是不同的.

       `'sed -e 's/\/\\/g'` 是不可用的,而 $(sed -e 's/\/\\/g') 是可用的           

       $ echo "`echo '\'`"      echo "$(echo '\')"   \      echo "`echo sed -e 's/\/\\/g'`"   sed -e s//\/g   $ echo "$(echo sed -e 's/\/\\/g')"   sed -e s/\/\\/g   
  2. 使用``嵌套時要將裡面的 `` 轉義.

``是比較舊的方式,現已漸被$()替換

ps: 個人認為 `` 寫在腳本中也不好看,符號太小,且易與 ' 混淆,建議不要使用.

2.5.5 Arithmetic Expansion (數學擴展)

$(( expression ))

2.5.6 Process Substitution (進程替換)

<(list) or >(list)

Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files.

例子

   $ diff <(printf "%sn" a b c) <(printf "%sn" a b c)   $ diff <(printf "%sn" a b c) <(printf "%sn" a bb c)   2c2   < b   ---   > bb   $ paste <(printf "%sn" a b c) <(printf "%sn" a bb c)   a   a   b   bb   c   c           

可用於將 list | while read l ; do ...; done 替換為 while read l ; do ...; done < <(list) 這種形式,從而避免 while 循環於子 shell 執行.

2.5.7 Word Splitting (單詞分割)

2.5.8 Pathname Expansion (路徑擴展)

通過 pattern matching 進行擴展.

From bash manual

   *      Matches any string, including the null string.  When the globstar shell option is enabled, and * is used in a filename expansion context,  two  adja          cent  *s  used  as  a  single pattern will match all files and zero or more directories and subdirectories.  If followed by a /, two adjacent *s will          match only directories and subdirectories.   ?      Matches any single character.   [...]  Matches any one of the enclosed characters.  A pair of characters separated by a hyphen denotes a range expression; any character that sorts  between          those two characters, inclusive, using the current locale's collating sequence and character set, is matched.  If the first character following the [          is a !  or a ^ then any character not enclosed is matched.  The sorting order of characters in range expressions is determined by the current  locale          and  the  value  of the LC_COLLATE shell variable, if set.  A - may be matched by including it as the first or last character in the set.  A ] may be          matched by including it as the first character in the set.             Within [ and ], character classes can be specified using the syntax [:class:], where class is one of the following classes defined in the POSIX stan          dard:          alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit          A character class matches any character belonging to that class.  The word character class matches letters, digits, and the character _.             Within [ and ], an equivalence class can be specified using the syntax [=c=], which matches all characters with the same collation weight (as defined          by the current locale) as the character c.             Within [ and ], the syntax [.symbol.] matches the collating symbol symbol.           

路徑擴展是在單詞割之後進行,所以如路徑名中有空格,該路徑也只會做為一個參數傳入.

所以,一般來說這種寫法 for f in $(ls $dir) ; do ... ; done 不如 for f in $dir/* ; do ...; done

2.5.9 Quote Removal (引號去除)

After the preceding expansions, all unquoted occurrences of the characters , ', and " that did not result from one of the above expansions are removed.

2.6 Tips

2.6.1 空字元串測試

   $ var=   $ [ -z "$var" ] ; echo $?   0   $ [ -n "$var" ] ; echo $?   1   $ [ -z $var ] ; echo $?   0   $ [ -n $var ] ; echo $?   0   

在用 -n 進行字元串不為空的測試時,一定要將所測試的變數用 "" 引起來.

2.6.2 大小寫轉換

bash 一般的做法是通過外部命令來實現,或自己寫個函數來做.

  • tr '[:lower:]' '[:upper:]'
  • sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
  • awk '{print toupper($0)}'

在較高版本的bash中可用以下方法

  • declare -l, declare -u 然後對變數賦值.
  • ${parameter^pattern} ${parameter^^pattern} ${parameter,pattern} ${parameter,,pattern}

2.6.3 隨機數

$RANDOM 產生 0 - 32767 之間隨機數,要產生更大的隨要數,可以以 $RANDOM 為基礎做一個函數. 也可以像 hexdump -e '"%un"' -n 4 /dev/random 這樣去讀 /dev/random

2.6.4 read

不對 轉義

read 讀一行時會對 轉義,一般來說是沒用的,需加上 -r 參數.

REPLY

read時會去掉頭尾的空白,如需要保留,則read后不要跟變數,用 $REPLY 訪問讀到的內容.

如對一個文本文件進行通過read進行複製可以:

while read -r ; do echo "$REPLY" ; doen <input >output

while read line

需防止 while 中的命令去讀 stdin

   printf "%sn" localhost localhost | while read host ; do ssh $host whoami ; done   

這樣是有問題的,正確的方法可為

   printf "%sn" localhost localhost | while read host ; do ssh -n $host whoami ; done   printf "%sn" localhost localhost | while read host ; do ssh $host whoami </dev/null ; done      exec 3< <(printf "%sn" localhost localhost)   while read -u3 host ; do ssh $host whoami ; done   exec 3<&-   

2.6.5 $cmd 與 eval $cmd

見: http://fvue.nl/wiki/Bash:_Why_use_eval_with_variable_expansion?

$cmd 一般會有問題,大概是這樣理解的 :

$cmd 會最先做一個syntax parser,然後再參數擴展,然後會到 word splitting. cmd='echo "a b"' , $cmd 在word splitting後會變成 echo '"a' 'b"'

要只被交到 word splitting 的就是按IFS來分的了,如

   $ echo $(echo '"a          b"')   "a b"   $ echo "$(echo '"a          b"')"   "a          b"   

所以會被分成那個鳥樣.

如cmd中有參數,那麼 "$cmd" 這樣直接執行一般不會有結果,返回值是127,就是找不到命令.

而 eval 是相當於對 擴展好的 cmd 再走了一下解釋流程,所以沒有問題.

結論:不要用 $cmd 要用 eval "$cmd"

2.6.6 local是個內建命令

不要用 local a="a_value" b="${a} b value"

local 是個命令,跟bash中賦值語句的執行是不一樣的.

例子

   $ cat t.sh   #!/bin/bash      function t1()   {       local a=t1 b=$a.bb       echo "a:[$a] b:[$b]"   }      function t2()   {       a=t2 b=$a.bb       echo "a:[$a] b:[$b]"   }      t1   t2   t1   $ ./t.sh   a:[t1] b:[.bb]   a:[t2] b:[t2.bb]   a:[t1] b:[t2.bb]           

同理,export也是一樣的.

2.6.7 賦值語句後跟命令

命令前有賦值(如 PATH=/usr/bin env ),那個這個賦值只對這個命令本身有效,不會影響當前環境. 所以這個賦值一般要是環境變數才行,不然應該一點用都沒有.

常用的形式有 IFS=: read v1 v2 v3

2.6.8 將結果打到標準輸出和錯誤輸出

   echo hello              # stdout   echo hello 1>&2         # stderr   

上面是必需必需的, 還可以通過重定向到以下文件來指定:

/dev/stdout /dev/stderr

/dev/fd/1 /dev/fd/2

/proc/$$/fd/1 /proc/$$/fd/2

/proc/self/fd/1 /proc/self/fd/2

2.6.9 子shell

子shell中的變數對於子shell之外的代碼塊來說, 是不可見的. 當然, 父進程也不能訪問這些變數.

圓括弧中的命令列表

(command;command;...; command)

可用於進入一個目錄操作再退出

   (   cd $dir   .... # do something   )   

管道連接的命令

From bash manual

   Each command in a pipeline is executed as a separate process (i.e., in a subshell)   

常見的一個問題

   num=1   seq 1 5 | while read l ; do num=$((num 1)); done   echo $num   

可使用進程替換解決

   num=1   while read l ; do num=$((num 1)); done < <(seq 1 5)   echo $num   

不支持進程替換的可用命名管道解決

   mkfifo t_fifo   seq 1 5 >t_fifo &   num=1   while read l ; do num=$((num 1)); done <t_fifo   echo $num   

命令替換中的命令列表

   $ a=aa   $ echo $(a=bb;echo $a)   bb   $ echo $a   aa   

2.6.10

:(){ :|: & };:

fork炸彈,造成死機,危險.

解釋

   :()   {       : | : &   }   :   

定義了一個名為 ':' 的遞歸函數,然後調用.

ps: ':' 是一個啥事不幹的內建命令,可用於佔位,如

   if [ $v1 -lt v2 ] ; then       :   else       echo do something   fi   

2.6.11 調試

  • bash -n ./scritp 只做語法檢查,不執行
  • set -x Print commands and their arguments as they are executed. (set x 關閉)
  • 插入 echo, printf 等列印語句調試
  • 對重要的的命令可在調度階段只 echo 出命令及其參數確定沒問題后再改為執行. 如 rm -rf $dir 這樣的危險命令也建議先採用這個方法.


[火星人 ] Bash Use And Programming已經有838次圍觀

http://coctec.com/docs/linux/show-post-49714.html