📄 basics-reviewed.bash
字号:
# The Extended-Syntax string operations can be applied to all#+ elements of an array.#### This may be thought of as a For-Each operation on a vector of strings.#### Parameters are similar to an array.# The initialization of a parameter array for a script#+ and a parameter array for a function only differ#+ in the initialization of ${0}, which never changes its setting.#### Subscript zero of the script's parameter array contains#+ the name of the script.#### Subscript zero of a function's parameter array DOES NOT contain#+ the name of the function.# The name of the current function is accessed by the $FUNCNAME variable.#### A quick, review list follows (quick, not short).echoecho '- - Test (but not change) - -'echo '- null reference -'echo -n ${VarNull-'NotSet'}' ' # NotSetecho ${VarNull} # NewLine onlyecho -n ${VarNull:-'NotSet'}' ' # NotSetecho ${VarNull} # Newline onlyecho '- null contents -'echo -n ${VarEmpty-'Empty'}' ' # Only the spaceecho ${VarEmpty} # Newline onlyecho -n ${VarEmpty:-'Empty'}' ' # Emptyecho ${VarEmpty} # Newline onlyecho '- contents -'echo ${VarSomething-'Content'} # Literalecho ${VarSomething:-'Content'} # Literalecho '- Sparse Array -'echo ${ArrayVar[@]-'not set'}# ASCII-Art time# State Y==yes, N==no# - :-# Unset Y Y ${# ... } == 0# Empty N Y ${# ... } == 0# Contents N N ${# ... } > 0# Either the first and/or the second part of the tests#+ may be a command or a function invocation string.echoecho '- - Test 1 for undefined - -'declare -i t_decT() { t=$t-1}# Null reference, set: t == -1t=${#VarNull} # Results in zero.${VarNull- _decT } # Function executes, t now -1.echo $t# Null contents, set: t == 0t=${#VarEmpty} # Results in zero.${VarEmpty- _decT } # _decT function NOT executed.echo $t# Contents, set: t == number of non-null charactersVarSomething='_simple' # Set to valid function name.t=${#VarSomething} # non-zero length${VarSomething- _decT } # Function _simple executed.echo $t # Note the Append-To action.# Exercise: clean up that example.unset tunset _decTVarSomething=Literalechoecho '- - Test and Change - -'echo '- Assignment if null reference -'echo -n ${VarNull='NotSet'}' ' # NotSet NotSetecho ${VarNull}unset VarNullecho '- Assignment if null reference -'echo -n ${VarNull:='NotSet'}' ' # NotSet NotSetecho ${VarNull}unset VarNullecho '- No assignment if null contents -'echo -n ${VarEmpty='Empty'}' ' # Space onlyecho ${VarEmpty}VarEmpty=''echo '- Assignment if null contents -'echo -n ${VarEmpty:='Empty'}' ' # Empty Emptyecho ${VarEmpty}VarEmpty=''echo '- No change if already has contents -'echo ${VarSomething='Content'} # Literalecho ${VarSomething:='Content'} # Literal# "Subscript sparse" Bash-Arrays#### Bash-Arrays are subscript packed, beginning with#+ subscript zero unless otherwise specified.#### The initialization of ArrayVar was one way#+ to "otherwise specify". Here is the other way:###echodeclare -a ArraySparseArraySparse=( [1]=one [2]='' [4]='four' )# [0]=null reference, [2]=null content, [3]=null referenceecho '- - Array-Sparse List - -'# Within double-quotes, default IFS, Glob-PatternIFS=$'\x20'$'\x09'$'\x0A'printf %q "${ArraySparse[*]}"echo# Note that the output does not distinguish between "null content"#+ and "null reference".# Both print as escaped whitespace.#### Note also that the output does NOT contain escaped whitespace#+ for the "null reference(s)" prior to the first defined element.#### This behavior of 2.04, 2.05a and 2.05b has been reported#+ and may change in a future version of Bash.# To output a sparse array and maintain the [subscript]=value#+ relationship without change requires a bit of programming.# One possible code fragment:#### local l=${#ArraySparse[@]} # Count of defined elements# local f=0 # Count of found subscripts# local i=0 # Subscript to test( # Anonymous in-line function for (( l=${#ArraySparse[@]}, f = 0, i = 0 ; f < l ; i++ )) do # 'if defined then...' ${ArraySparse[$i]+ eval echo '\ ['$i']='${ArraySparse[$i]} ; (( f++ )) } done)# The reader coming upon the above code fragment cold#+ might want to review "command lists" and "multiple commands on a line"#+ in the text of the foregoing "Advanced Bash Scripting Guide."#### Note:# The "read -a array_name" version of the "read" command#+ begins filling array_name at subscript zero.# ArraySparse does not define a value at subscript zero.#### The user needing to read/write a sparse array to either#+ external storage or a communications socket must invent#+ a read/write code pair suitable for their purpose.#### Exercise: clean it up.unset ArraySparseechoecho '- - Conditional alternate (But not change)- -'echo '- No alternate if null reference -'echo -n ${VarNull+'NotSet'}' 'echo ${VarNull}unset VarNullecho '- No alternate if null reference -'echo -n ${VarNull:+'NotSet'}' 'echo ${VarNull}unset VarNullecho '- Alternate if null contents -'echo -n ${VarEmpty+'Empty'}' ' # Emptyecho ${VarEmpty}VarEmpty=''echo '- No alternate if null contents -'echo -n ${VarEmpty:+'Empty'}' ' # Space onlyecho ${VarEmpty}VarEmpty=''echo '- Alternate if already has contents -'# Alternate literalecho -n ${VarSomething+'Content'}' ' # Content Literalecho ${VarSomething}# Invoke functionecho -n ${VarSomething:+ $(_simple) }' ' # SimpleFunc Literalecho ${VarSomething}echoecho '- - Sparse Array - -'echo ${ArrayVar[@]+'Empty'} # An array of 'Empty'(ies)echoecho '- - Test 2 for undefined - -'declare -i t_incT() { t=$t+1}# Note:# This is the same test used in the sparse array#+ listing code fragment.# Null reference, set: t == -1t=${#VarNull}-1 # Results in minus-one.${VarNull+ _incT } # Does not execute.echo $t' Null reference'# Null contents, set: t == 0t=${#VarEmpty}-1 # Results in minus-one.${VarEmpty+ _incT } # Executes.echo $t' Null content'# Contents, set: t == (number of non-null characters)t=${#VarSomething}-1 # non-null length minus-one${VarSomething+ _incT } # Executes.echo $t' Contents'# Exercise: clean up that example.unset tunset _incT# ${name?err_msg} ${name:?err_msg}# These follow the same rules but always exit afterwards#+ if an action is specified following the question mark.# The action following the question mark may be a literal#+ or a function result.#### ${name?} ${name:?} are test-only, the return can be tested.# Element operations# ------------------echoecho '- - Trailing sub-element selection - -'# Strings, Arrays and Positional parameters# Call this script with multiple arguments#+ to see the parameter selections.echo '- All -'echo ${VarSomething:0} # all non-null charactersecho ${ArrayVar[@]:0} # all elements with contentecho ${@:0} # all parameters with content; # ignoring parameter[0]echoecho '- All after -'echo ${VarSomething:1} # all non-null after character[0]echo ${ArrayVar[@]:1} # all after element[0] with contentecho ${@:2} # all after param[1] with contentechoecho '- Range after -'echo ${VarSomething:4:3} # ral # Three characters after # character[3]echo '- Sparse array gotch -'echo ${ArrayVar[@]:1:2} # four - The only element with content. # Two elements after (if that many exist). # the FIRST WITH CONTENTS #+ (the FIRST WITH CONTENTS is being #+ considered as if it #+ were subscript zero).# Executed as if Bash considers ONLY array elements with CONTENT# printf %q "${ArrayVar[@]:0:3}" # Try this one# In versions 2.04, 2.05a and 2.05b,#+ Bash does not handle sparse arrays as expected using this notation.## The current Bash maintainer, Chet Ramey, has corrected this#+ for an upcoming version of Bash.echo '- Non-sparse array -'echo ${@:2:2} # Two parameters following parameter[1]# New victims for string vector examples:stringZ=abcABC123ABCabcarrayZ=( abcabc ABCABC 123123 ABCABC abcabc )sparseZ=( [1]='abcabc' [3]='ABCABC' [4]='' [5]='123123' )echoecho ' - - Victim string - -'$stringZ'- - 'echo ' - - Victim array - -'${arrayZ[@]}'- - 'echo ' - - Sparse array - -'${sparseZ[@]}'- - 'echo ' - [0]==null ref, [2]==null ref, [4]==null content - 'echo ' - [1]=abcabc [3]=ABCABC [5]=123123 - 'echo ' - non-null-reference count: '${#sparseZ[@]}' elements'echoecho '- - Prefix sub-element removal - -'echo '- - Glob-Pattern match must include the first character. - -'echo '- - Glob-Pattern may be a literal or a function result. - -'echo# Function returning a simple, Literal, Glob-Pattern_abc() { echo -n 'abc'}echo '- Shortest prefix -'echo ${stringZ#123} # Unchanged (not a prefix).echo ${stringZ#$(_abc)} # ABC123ABCabcecho ${arrayZ[@]#abc} # Applied to each element.# Fixed by Chet Ramey for an upcoming version of Bash.# echo ${sparseZ[@]#abc} # Version-2.05b core dumps.# The -it would be nice- First-Subscript-Of# echo ${#sparseZ[@]#*} # This is NOT valid Bash.echoecho '- Longest prefix -'echo ${stringZ##1*3} # Unchanged (not a prefix)echo ${stringZ##a*C} # abcecho ${arrayZ[@]##a*c} # ABCABC 123123 ABCABC# Fixed by Chet Ramey for an upcoming version of Bash# echo ${sparseZ[@]##a*c} # Version-2.05b core dumps.echoecho '- - Suffix sub-element removal - -'echo '- - Glob-Pattern match must include the last character. - -'echo '- - Glob-Pattern may be a literal or a function result. - -'echoecho '- Shortest suffix -'echo ${stringZ%1*3} # Unchanged (not a suffix).echo ${stringZ%$(_abc)} # abcABC123ABCecho ${arrayZ[@]%abc} # Applied to each element.# Fixed by Chet Ramey for an upcoming version of Bash.# echo ${sparseZ[@]%abc} # Version-2.05b core dumps.# The -it would be nice- Last-Subscript-Of# echo ${#sparseZ[@]%*} # This is NOT valid Bash.echoecho '- Longest suffix -'echo ${stringZ%%1*3} # Unchanged (not a suffix)echo ${stringZ%%b*c} # aecho ${arrayZ[@]%%b*c} # a ABCABC 123123 ABCABC a# Fixed by Chet Ramey for an upcoming version of Bash.# echo ${sparseZ[@]%%b*c} # Version-2.05b core dumps.echoecho '- - Sub-element replacement - -'echo '- - Sub-element at any location in string. - -'echo '- - First specification is a Glob-Pattern - -'echo '- - Glob-Pattern may be a literal or Glob-Pattern function result. - -'echo '- - Second specification may be a literal or function result. - -'echo '- - Second specification may be unspecified. Pronounce that'echo ' as: Replace-With-Nothing (Delete) - -'echo# Function returning a simple, Literal, Glob-Pattern_123() { echo -n '123'}echo '- Replace first occurrence -'echo ${stringZ/$(_123)/999} # Changed (123 is a component).echo ${stringZ/ABC/xyz} # xyzABC123ABCabcecho ${arrayZ[@]/ABC/xyz} # Applied to each element.echo ${sparseZ[@]/ABC/xyz} # Works as expected.echoecho '- Delete first occurrence -'echo ${stringZ/$(_123)/}echo ${stringZ/ABC/}echo ${arrayZ[@]/ABC/}echo ${sparseZ[@]/ABC/}# The replacement need not be a literal,#+ since the result of a function invocation is allowed.# This is general to all forms of replacement.echoecho '- Replace first occurrence with Result-Of -'echo ${stringZ/$(_123)/$(_simple)} # Works as expected.echo ${arrayZ[@]/ca/$(_simple)} # Applied to each element.echo ${sparseZ[@]/ca/$(_simple)} # Works as expected.echoecho '- Replace all occurrences -'echo ${stringZ//[b2]/X} # X-out b's and 2'secho ${stringZ//abc/xyz} # xyzABC123ABCxyzecho ${arrayZ[@]//abc/xyz} # Applied to each element.echo ${sparseZ[@]//abc/xyz} # Works as expected.echoecho '- Delete all occurrences -'echo ${stringZ//[b2]/}echo ${stringZ//abc/}echo ${arrayZ[@]//abc/}echo ${sparseZ[@]//abc/}echoecho '- - Prefix sub-element replacement - -'echo '- - Match must include the first character. - -'echoecho '- Replace prefix occurrences -'echo ${stringZ/#[b2]/X} # Unchanged (neither is a prefix).echo ${stringZ/#$(_abc)/XYZ} # XYZABC123ABCabcecho ${arrayZ[@]/#abc/XYZ} # Applied to each element.echo ${sparseZ[@]/#abc/XYZ} # Works as expected.echoecho '- Delete prefix occurrences -'echo ${stringZ/#[b2]/}echo ${stringZ/#$(_abc)/}echo ${arrayZ[@]/#abc/}echo ${sparseZ[@]/#abc/}echoecho '- - Suffix sub-element replacement - -'echo '- - Match must include the last character. - -'echoecho '- Replace suffix occurrences -'echo ${stringZ/%[b2]/X} # Unchanged (neither is a suffix).echo ${stringZ/%$(_abc)/XYZ} # abcABC123ABCXYZecho ${arrayZ[@]/%abc/XYZ} # Applied to each element.echo ${sparseZ[@]/%abc/XYZ} # Works as expected.echoecho '- Delete suffix occurrences -'echo ${stringZ/%[b2]/}echo ${stringZ/%$(_abc)/}echo ${arrayZ[@]/%abc/}echo ${sparseZ[@]/%abc/}echoecho '- - Special cases of null Glob-Pattern - -'echoecho '- Prefix all -'# null substring pattern means 'prefix'echo ${stringZ/#/NEW} # NEWabcABC123ABCabcecho ${arrayZ[@]/#/NEW} # Applied to each element.echo ${sparseZ[@]/#/NEW} # Applied to null-content also. # That seems reasonable.echoecho '- Suffix all -'# null substring pattern means 'suffix'echo ${stringZ/%/NEW} # abcABC123ABCabcNEWecho ${arrayZ[@]/%/NEW} # Applied to each element.echo ${sparseZ[@]/%/NEW} # Applied to null-content also. # That seems reasonable.echoecho '- - Special case For-Each Glob-Pattern - -'echo '- - - - This is a nice-to-have dream - - - -'echo_GenFunc() { echo -n ${0} # Illustration only. # Actually, that would be an arbitrary computation.}# All occurrences, matching the AnyThing pattern.# Currently //*/ does not match null-content nor null-reference.# /#/ and /%/ does match null-content but not null-reference.echo ${sparseZ[@]//*/$(_GenFunc)}# A possible syntax would be to make#+ the parameter notation used within this construct mean:# ${1} - The full element# ${2} - The prefix, if any, to the matched sub-element# ${3} - The matched sub-element# ${4} - The suffix, if any, to the matched sub-element## echo ${sparseZ[@]//*/$(_GenFunc ${3})} # Same as ${1} here.# Perhaps it will be implemented in a future version of Bash.exit 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -