6663
Comment:
|
285
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
<<Anchor(faq73)>> == How can I use parameter expansion? How can I get substrings? How can I get a file without its extension, or get just a file's extension? == Your shell has ''variables'' (either inherited from the environment, or defined by you), as well as several other ''special parameters'' like `$` (the shell's process ID) and so on. All of these are considered ''parameters'', and they can be expanded by putting a `$` in front. However, that's just the simplest case.... Parameter Expansion is far more general and powerful than that. (The full set of capabilities can be found in the [[http://tiswww.case.edu/php/chet/bash/bash.html#lbBA|bash manpage]], or see [[http://tiswww.tis.case.edu/~chet/bash/bashref.html#SEC31|the reference]] or [[http://bash-hackers.org/wiki/doku.php?id=syntax:pe|the bash hackers article]] about it). It can be hard to understand parameter expansion without actually using it, so we're going to begin with some examples. The first set of capabilities involves ''removing a substring'', from either the beginning or the end of a parameter. Here's an example using parameter expansion with something akin to a hostname (dot-separated components): {{{ parameter result ----------- ------------------------------ ${NAME} polish.ostrich.racing.champion ${NAME#*.} ostrich.racing.champion ${NAME##*.} champion ${NAME%%.*} polish ${NAME%.*} polish.ostrich.racing }}} And here's an example of the parameter expansions for a typical filename: {{{ parameter result ----------- -------------------------------------------------------- ${FILE} /usr/share/java-1.4.2-sun/demo/applets/Clock/Clock.class ${FILE#*/} usr/share/java-1.4.2-sun/demo/applets/Clock/Clock.class ${FILE##*/} Clock.class ${FILE%%/*} ${FILE%/*} /usr/share/java-1.4.2-sun/demo/applets/Clock }}} US keyboard users may find it helpful to observe that, on the keyboard, the "#" is to the left of the "%" symbol. Mnemonically, "#" operates on the left side of a parameter, and "%" operates on the right. The [[glob]] after the "%" or "%%" or "#" or "##" specifies what pattern to ''remove'' from the parameter expansion. You cannot nest parameter expansions. If you need to perform two expansions steps, use a variable to hold the result of the first expansion: {{{ # foo holds: key="some value" bar=${foo#*=\"} bar=${bar%\"*} # now bar holds: some value }}} Here are a few more examples (but ''please'' see the real documentation for a list of all the features!). I include these mostly so people won't break the wiki again, trying to add new questions that answer this stuff. {{{ ${string:2:1} # The third character of string (0, 1, 2 = third) ${string:1} # The string starting from the second character # Note: this is equivalent to ${string#?} ${string%?} # The string with its last character removed. ${string: -1} # The last character of string ${string:(-1)} # The last character of string, alternate syntax # Note: string:-1 means something entirely different; see below. ${file%.mp3} # The filename without the .mp3 extension # Very useful in loops of the form: for file in *.mp3; do ... ${file%.*} # The filename without its extension (assuming there was # only one extension in the first place...). ${file%%.*} # The filename without all of its extensions ${file##*.} # The extension only. }}} === Parameter Expansion on Arrays === [[BashFAQ/005|BASH arrays]] are remarkably flexible, since they are so well integrated with the other shell expansions. Virtually any expansion you can carry out on a scalar can equally be applied to a whole array. Remember that quoting an array expansion using @ (e.g. {{{"$@"}}} or {{{"${cmd[@]}"}}}) results in the members being treated as individual words, regardless of their content. So for example, {{{arr=("${list[@]}" foo)}}} correctly handles all elements in the `list` array. First the expansions: {{{ $ a=(alpha beta gamma) # our base array $ echo "${a[@]#a}" # chop 'a' from the beginning of every member lpha beta gamma $ echo "${a[@]%a}" # from the end alph bet gamm $ echo "${a[@]//a/f}" # substitution flphf betf gfmmf }}} The following expansions (substitute at beginning or end) are very useful for the next part: {{{ $ echo "${a[@]/#a/f}" # substitute a for f at start flpha beta gamma $ echo "${a[@]/%a/f}" # at end alphf betf gammf }}} We use these to prefix or suffix every member of the list: {{{ $ echo "${a[@]/#/a}" # append a to beginning aalpha abeta agamma # (thanks to floyd-n-milan for this) $ echo "${a[@]/%/a}" # append a to end alphaa betaa gammaa }}} This works by substituting an empty string at beginning or end with the value we wish to append. So finally, a quick example of how you might use this in a script, say to add a user-defined prefix to every target: {{{ $ PFX=inc_ $ a=("${a[@]/#/$PFX}") $ echo "${a[@]}" inc_alpha inc_beta inc_gamma }}} This is very useful, as you might imagine, since it saves looping over every member of the array. The special parameter `@` can also be used as an array for purposes of parameter expansions: {{{ ${@:(-2):1} # the second-to-last parameter ${@: -2:1} # alternative syntax }}} You can't use `${@:-2:1}`, however, because that collides with the syntax in the next section. === Portability === The original Bourne shell (7th edition Unix) only supports a very limited set of parameter expansion options: {{{ ${var-word} # if var is defined, use var; otherwise, "word" ${var+word} # if var is defined, use "word"; otherwise, nothing ${var=word} # if var is defined, use var; otherwise, use "word" AND... # also assign "word" to var ${var?error} # if var is defined, use var; otherwise print "error" and exit }}} These are the only completely portable expansions available. POSIX shells (as well as KornShell and [[BASH]]) offer those, plus a slight variant: {{{ ${var:-word} # if var is defined AND NOT EMPTY, use var; otherwise, "word" etc. }}} POSIX, Korn (all versions) and Bash all support the `${var#word}`, `${var%word}`, `${var##word}` and `${var%%word}` expansions. ksh88 does not support `${var/replace/with}` or `${var//replace/all}`, but ksh93 and Bash do. ksh88 does not support fancy expansion with arrays (e.g., `${a[@]%.gif}`) but ksh93 and Bash do. |
Financial Industry Dealer Shayne Gilpatric from Laval, has hobbies for instance r/c helicopters, compte brazzers gratuit ([[http://www.comptebrazzersgratuit.fr|he has a good point]]) and spelunkering. Finds the globe an enjoyable place having spent 7 weeks at Episcopal City of Albi. |
Financial Industry Dealer Shayne Gilpatric from Laval, has hobbies for instance r/c helicopters, compte brazzers gratuit (he has a good point) and spelunkering. Finds the globe an enjoyable place having spent 7 weeks at Episcopal City of Albi.