Differences between revisions 4 and 42 (spanning 38 versions)
Revision 4 as of 2007-11-22 23:47:28
Size: 4856
Editor: MrIgli
Comment: <igli> added array expansions
Revision 42 as of 2016-05-04 03:41:10
Size: 285
Editor: TraceyShea
Comment:
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? ==

Parameter Expansion is a separate section of the [http://tiswww.case.edu/php/chet/bash/bash.html#lbBA bash manpage] (also {{{man bash -P 'less -p "^ Parameter Expansion"'}}} or see [http://tiswww.tis.case.edu/~chet/bash/bashref.html#SEC30 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. (DO NOT think about parameter expansion like a regex. It is different and distinct.)

Here's an example of how to use 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
}}}

You cannot nest parameter expansions. If you need to perform two separate expansions, use a temporary variable to hold the result of the first expansion.

You may find it helpful to associate that, on your keyboard, the "#" is to the left of the "$" symbol and the "%" symbol is to its right; this corresponds with their acting upon the left (beginning) and right (end) parts of the parameter.

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.

${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 ===
BASH arrays are remarkably flexible, since they are so well integrated with the other shell expansions. Any expansion you can carry out on a scalar can equally be applied to the whole list in an array. Remember that quoting an array expansion using @, eg {{{"$@"}}} or {{{"${cmd[@]}"}}} results in the members being treated as individual words, irrespective of their content. So for example, {{{arr=("${list[@]}" foo)}}} correctly handles all parameters in the list; we use this to modify an array in place.

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.

==== Portability ====
Since arrays are not portable, nor is their expansion.
(Anyone know if ksh does this?)
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.

BashFAQ/073 (last edited 2023-06-24 09:33:51 by emanuele6)