星期日, 10月 28, 2018

bash PARAMETERS

bash 或其它 shell 的參數 (parameter),是一個儲存值的地方,可以是
  • 變數 (variable),名稱 (name) 非數字開頭由英文字母、數字及「_」組成的字,有一個值,並有屬性 (attribute) 可由內建指令 declare 指定。陣列。Shell 有內動的變數。
  • 一個數字
  • 一個特殊字元
參數經過指定或空字串 (沒) 產生。
參數=[]
透過內建指令 unset 移除。

所有值會經歷 tilde 擴展、參數和變數擴展、指令取代、算術擴展、及 quote 移除 (見 EXPANSION)。如果變數的屬性為整數 (integer),即使沒 $((...)) 也會以[算術表示式](見 bash Arithmetic Expansion) evaluated。除了「$@」外,不進行 Word splitting。不進行 Pathname expansion。變數指定亦可放在內建指令 alias、declare、typeset、export、readonly、及 local (declaration 指令) 的引數。
當用在 posix 模式,這些內建指令 may appear in a command after one or more instances of the command builtin and retain these assignment statement properties。

使用 += 運算指定一個值給 shell 變數或 array index 可進行 append 或加法運算,包括前面接受變數指定作為引數的內建指令。:
  • 整數變數:加法運算加上目前的值。
  • 使用 compound assignment 應用在陣列:indexed 陣列最後會多加一個值,associative 陣列新增 key-value 對。
  • 字串變數:值擴展後附加到字串後面。

Positional Parameters 位置參數

位置參數是從 1 開始的數字,由執行時的引數依序指定,不能由指定 statement 指定,可由內建指令 set 重新指定。執行 shell 函數時,位置參數暫時由函數引數取代。

當位置參數是多位數字時,需要用 braces 括起來。

註:$0 不算是位置參數。

Special Parameters 特殊參數

只能讀,不能指定。
*從 1 開始的所有位置參數,每個位置參數擴展為個別的字。依據進行的 context,可能會進行進一步 word splitting 和 pathname expansion。如果在雙引號裡面 ("$*"),擴展為一個字。位置參數間由特殊變數 IFS 第一個字元連接起來的。如果 IFS 沒設,則用 space 連接。如果 IFS 是 null,則不插入字元直接連接。
@從 1 開始的所有位置參數。如果在雙引號裡面 ("$@"),每個位置參數擴展為個別的字,相當於 "$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.
#位置參數的數目。
?最後前景執行 pipeline 的 exit statu。
-目前 option flags。
$shell 的 process ID。在 ()  subshell,是 current shell 的 process ID,不是 subshell 的。
!最後背景執行的 process ID。
0shell 或 shell script 的名稱。
_shell 一開始時,設為 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  executed  and placed  in  the  environment  exported  to  that command.  When checking mail, this parameter holds the name of the  mail  file currently being checked.

Shell Variables

下列變數由 shell 設定:
BASH:執行的完整檔名。
BASHOPTS
BASHPID
BASH_ARGC
BASH_ARGV
BASH_CMDS
BASH_COMMAND
BASH_EXECUTION_STRING
BASH_LINENO



BASH_REMATCH
由指令 [[ 的 =~ 運算指定的唯讀陣列,其中 index 0 是整個比對符合的字串,index n 是 第 n 個 parenthesized subexpression 比對的結果。
BASH_SOURCE
BASH_SUBSHELL
BASH_VERSINFO
BASH_VERSION
COMP_CWORD
COMP_KEY
COMP_LINE
COMP_POINT
COMP_TYPE
COMP_WORDBREAKS
COMP_WORDS
COPROC
DIRSTACK
EUID
FUNCNAME
GROUPS
HISTCMD
HOSTNAME
HOSTTYPE
LINENO
MACHTYPE
MAPFILE
OLDPWD
OPTARG
OPTIND
OSTYPE
PIPESTATUS
PPID
PWD
RANDOM
READLINE_LINE
READLINE_POINT
REPLY
SECONDS
SHELLOPTS
SHLVL
UID

下列變數 shell 會使用到,有時 bash 會指定預設值:

BASH_COMPAT
BASH_ENV
BASH_XTRACEFD
CDPATH
CHILD_MAX
COLUMNS
COMPREPLY
EMACS
ENV
FCEDIT
FIGNORE
FUNCNEST
GLOBIGNORE
HISTCONTROL
HISTFILE
HISTFILESIZE
HISTIGNORE
HISTSIZE
HISTTIMEFORMAT


HOME
目前使用者的家目錄。作為內建指令 cd 的預設引數及進行 tilde 擴展用。

每個使用者帳戶在 /etc/passwd 會有一行,包含用「:」分隔的 7 個欄位,其中最後第二欄是使用者的家目錄,login 程式用來設 $HOME。
HOSTFILE
IFS
IGNOREEOF
INPUTRC
LANG
LC_ALL
LC_COLLATE
LC_CTYPE
LC_MESSAGES
LC_NUMERIC

LINES
MAIL
MAILCHECK
MAILPATH
OPTERR
PATH
POSIXLY_CORRECT
PROMPT_COMMAND
PROMPT_DIRTRIM
PS1
PS2
PS3
PS4
SHELL
TIMEFORMAT
TMOUT
TMPDIR
auto_resume
histchars

Arrays

nameref 參考變數

變數可使用內建指令 declare 或 local 的 -n 選項設定 nameref 屬性,參照另一個變數,讓變數間接修改,此時除了改變 nameref 屬性外,指定、移除和其它屬性修改都進行在參照的變數。
declare -n ref=$R #建立 nameref 變數 ref
unset ref #移除變數 $R
unset -n ref #移除 nameref ref

nameref 常用在 shell 函數裡參照函數引數。例如在 shell 函數裡:
declare -n ref=$1
建立 nameref 變數 ref 參照第 1 個引數。

如果 for 迴圈的 control variable 有 nameref 屬性, the list of words can be a list of shell variables, and a name reference will be established for each word in the list, in turn,  when the loop is executed.

陣列變數不能指定 nameref 屬性,但 nameref 變數可以參照陣列變數和 subscripted  array variables。

參考

man bash 的 PARAMETERS

星期日, 10月 07, 2018

bash EXPANSION

bash 指令行切成字後會進行7 種擴展,依下列順序:
  1. brace ({}):
  2. tilde (~):目錄擴展
  3. $ parameter and variable 擴展、arithmetic 擴展、command substitution ($)
  4. word splitting:上面 ($) 類擴展如不在雙引號內,會依據 IFS 進行字切割。
  5. pathname
有些系統還支援額外的 process substitution,在上述順序 2 和 3 同時進行。

最後移除一開始就有的、未 quoted 的 quote 字元。

只有 brace expansion, word splitting, 及 pathname expansion 會改變字的數目,其它擴展擴展一個字為一個字,唯一的例外是 "$@" 及 "${name[@]}" 的擴展 (見 PARAMETERS).

Brace Expansion {}

{} 間一系列以「,」區隔的字串個別擴展為 word,或是兩個數字或兩個單一字元以「..」區隔的序列擴展 {x..y[..incr]}。序列擴展如果是數字的,前面可以加 0 來嘗試強迫產生相同位
數的數字。數字或字元間的序列擴展預設的增減值是 1 或 -1,可以再加「..數字」設定增減值。{} 裡可以有 {} 進行巢狀擴展。

「${」不做 brace 擴展,以免跟 parameter 擴展衝突。

例如
  • 「a{d,c,b}e」會擴展成「ade ace abe」
  • mkdir /usr/local/src/bash/{old,new,dist,bugs}
  • chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
傳統的 sh 沒有 Brace 擴展,要停用 Brace 擴展可以使用 +B 選項。

Tilde Expansion ~

tilde-prefix

Parameter Expansion

$ 字元引入參數擴展、指令取代、或算術擴展。

$參數 或 ${參數} 取代為變數值,參數名稱可用 {} 包起來避免跟緊接著的字元有錯誤連結。名稱是兩位以上數子,必須用 {} 包起來。

間接變數

下面 word 的部份會進行 tilde expansion、參數擴展、指令取代、和算術擴展。


${parameter:-word}
當 parameter unset 或 null 時,使用預設值 word。
${parameter:=word}
當 parameter unset 或 null 時,使用預設值 word 並指定給 parameter。位置參數和特殊參數不能用這種方式指定。
${parameter:?word}
${parameter:+word}
${parameter:offset}
${parameter:offset:length}
${!prefix*}
${!prefix@}
${!name[*]}
${!name[@]}
${#parameter}
參數長度
${parameter#word}
移除字串開頭最短符合 word 的部份。
${parameter##word}
移除字串開頭最長符合 word 的部份。
${parameter%word}
移除字串結尾最短符合 word 的部份。
${parameter%%word}
移除字串結尾最長符合 word 的部份。
${parameter/pattern/string}
${parameter//pattern/string}
${parameter/#pattern/string}
???
${parameter^pattern}
${parameter^^pattern}
轉換成大寫。
${parameter,pattern}
${parameter,,pattern}
轉換成小寫。

Command Substitution 指令取代

$(指令) 或 `指令`,取代為指令執行的輸出 (移除最後換行)。

$(cat file) 可以用更快的 $(< file) 取代。

Arithmetic Expansion

$((expression))

Process Substitution

Word Splitting 切割字

Pathname Expansion 路徑擴展

Pattern Matching

Quote Removal

移除所有非上述擴展產生的,unquoted 用的「\」、「'」、及「"」。

參考

  1. man bash 的 EXPANSION 節
  2. http://godleon.blogspot.tw/2007/06/shell-script-linux-pipe.html