259 lines
9.2 KiB
HTML
259 lines
9.2 KiB
HTML
<!--startcut ==============================================-->
|
|
<!-- *** BEGIN HTML header *** -->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<HTML><HEAD>
|
|
<title>Variable Mangling in Bash with String Operators LG #57</title>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
|
|
ALINK="#FF0000">
|
|
<!-- *** END HTML header *** -->
|
|
|
|
<CENTER>
|
|
<A HREF="http://www.linuxgazette.com/">
|
|
<H1><IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.jpg"
|
|
WIDTH="600" HEIGHT="124" border="0"></H1></A>
|
|
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="correa4.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue57/eyler.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="eyler2.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
<P>
|
|
</CENTER>
|
|
|
|
<!--endcut ============================================================-->
|
|
|
|
<H4 ALIGN="center">
|
|
"Linux Gazette...<I>making Linux just a little more fun!</I>"
|
|
</H4>
|
|
|
|
<P> <HR> <P>
|
|
<!--===================================================================-->
|
|
|
|
<center>
|
|
<H1><font color="maroon">Variable Mangling in Bash with String Operators</font></H1>
|
|
<H4>By <a href="mailto:pate@gnu.org">Pat Eyler</a></H4>
|
|
</center>
|
|
<P> <HR> <P>
|
|
|
|
<!-- END header -->
|
|
|
|
|
|
|
|
|
|
<h3>Abstract</h3>
|
|
<p>Have you ever wanted to change the names of many files at once?
|
|
How about using a default value for a variable if it has no value?
|
|
These and many other options are available to you through string
|
|
operators in bash and other Bourne shell derived shells.
|
|
<p>String operators allow you to manipulate the contents of a variable
|
|
without having to write your own shell functions to do so. They are
|
|
provided through 'curly brace' syntax. Any variable can be displayed
|
|
like this <code>${foo}</code> without changing its meaning. This
|
|
functionality is often used to protect a variable name from
|
|
surrounding characters.<br>
|
|
<code>
|
|
<pre>
|
|
bash-2.02$ export foo=foo
|
|
bash-2.02$ echo ${foo}bar # foo exists so this works
|
|
foobar
|
|
bash-2.02$ echo $foobar # foobar doesn't exist, so this fails
|
|
|
|
bash-2.02$
|
|
</pre>
|
|
</code>
|
|
<br>
|
|
|
|
By the end of this article, you'll be able to use it for a whole lot more.
|
|
<hr width="70%">
|
|
<p>There are three kinds of variable substitution:<ul>
|
|
<li>Pattern Matching,
|
|
<li>Substitution,
|
|
<li>Command Substitution.
|
|
</ul>
|
|
I'll talk about the first two and leave command substitution for
|
|
another article.
|
|
<h3>Pattern Matching</h3>
|
|
<p>There are two kinds of pattern matching available, matching from
|
|
the left and matching from the right. The operators, with their
|
|
functions and an expample, are shown in the following table:
|
|
<center>
|
|
<table width=70%>
|
|
<tr>
|
|
<th>Operator</th>
|
|
<th>Function</th>
|
|
<th>Example</th>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td><code>${foo#t*is}</code></td>
|
|
<td>deletes the shortest possible match from the left</td>
|
|
<td>
|
|
<code>export $foo="this is a test"<br>echo ${foo#t*is}<br>is a test
|
|
</code>
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td><code>${foo##t*is}</code></td>
|
|
<td>deletes the longest possible match from the left</td>
|
|
<td>
|
|
<code>export $foo="this is a test"<br>echo ${foo#t*is}<br>a test
|
|
</code>
|
|
</td>
|
|
</tr><tr valign=top>
|
|
<td><code>${foo%t*st}</code></td>
|
|
<td>deletes the shortest possible match from the right</td>
|
|
<td>
|
|
<code>export $foo="this is a test"
|
|
<br>echo ${foo%t*st}<br>this is a
|
|
</code>
|
|
</td>
|
|
</tr><tr valign=top>
|
|
<td><code>${foo%%t*st}</code></td>
|
|
<td>deletes the longest possible match from the right</td>
|
|
<td>
|
|
<code>export $foo="this is a test"<br>echo ${foo#t*is}<br>
|
|
</code>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
<blockquote>
|
|
<p><b>Note:</b> <i>While the <code>#</code> and <code>%</code>
|
|
identifiers may not seem obvious, they have a convenient mnemonic.
|
|
The <code>#</code> key is on the left side of the <code>$</code> key
|
|
and operates from the left. The <code>%</code> key is on the right of
|
|
the <code>$</code> key and operated from the right.</i>
|
|
</blockquote>
|
|
<p>These operators can be used to do a variety of things. For example,
|
|
the following script will change the extension of all '.html' files to
|
|
'.htm'.
|
|
<blockquote>
|
|
<code>
|
|
<pre>
|
|
#!/bin/bash
|
|
# quickly convert html filenames for use on a dossy system
|
|
# only handles file extensions, not file names
|
|
|
|
for i in *.html; do
|
|
if [ -f ${i%l} ]; then
|
|
echo ${i%l} already exists
|
|
else
|
|
mv $i ${i%l}
|
|
fi
|
|
done
|
|
|
|
</pre>
|
|
</code>
|
|
</blockquote>
|
|
|
|
<h3>Substitution</h3>
|
|
<p>Another kind of variable mangling you might want to employ is
|
|
substitution. There are four substitution operators in Bash. They
|
|
are shown in the following table:
|
|
<center>
|
|
<table width=70%>
|
|
<tr>
|
|
<th>Operator</th>
|
|
<th>Function</th>
|
|
<th>Example</th>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td><code>${foo:-bar}</code></td>
|
|
<td>If $foo exists and is not null, return $foo. If it doesn't exist,
|
|
or is null, return bar.</td>
|
|
<td>
|
|
<code>export foo=""<br>echo ${foo:-one}<br>one<br>echo $foo<br>
|
|
</code>
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td><code>${foo:=bar}</code></td>
|
|
<td>If $foo exists and is not null, return $foo. If it doesn't exist,
|
|
or is null, set $foo to bar and return bar</td>
|
|
<td>
|
|
<code>export foo=""<br>echo ${foo:=one}<br>one<br>echo $foo<br>one
|
|
</code>
|
|
</td>
|
|
</tr><tr valign=top>
|
|
<td><code>${foo:+bar}</code></td>
|
|
<td>If $foo exists and is not null, return bar. If it doesn't exist,
|
|
or is null, return a null.</td>
|
|
<td>
|
|
<code>export foo="this is a test"
|
|
<br>echo ${foo:+bar}<br>bar
|
|
</code>
|
|
</td>
|
|
</tr><tr valign=top>
|
|
<td><code>${foo:?"error message"}</code></td>
|
|
<td>If $foo exists and isn't null, return it's value. If it doesn't
|
|
exist, or is null, print the error message. If no error message is
|
|
given, it prints <code>parameter null or not
|
|
set</code>.<br><b>Note:</b> <i>In a non-interactive shell, this will
|
|
abort the current script. In an interactive shell, this will just
|
|
print the error message.</i>
|
|
</td>
|
|
<td>
|
|
<code>
|
|
export foo="one"<br>
|
|
for i in foo bar baz; do<br>
|
|
eval echo \${$foo:?}<br>
|
|
one<br>
|
|
bash: bar: parameter null or not set<br>
|
|
bash: baz: parameter null or not set<br>
|
|
</code>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
<blockquote>
|
|
<b>Note:</b> <i>The <code>:</code> in the above operators can be
|
|
omitted. Doing so changes the behavior of the operator to only test
|
|
for existence of the variable. This will cause the creation of a variable
|
|
in the case of</i> <code>${foo=bar}</code>
|
|
</blockquote>
|
|
<p>These operators can be used in a variety of ways. A good example
|
|
would be to give a default value to a variable normally read from the
|
|
command line arguments when no arguments are given. This is shown in
|
|
the following script.
|
|
|
|
<blockquote>
|
|
<code>
|
|
<pre>
|
|
#!/bin/bash
|
|
|
|
export INFILE=${1-"infile"}
|
|
|
|
export OUTFILE=${2-"outfile"}
|
|
|
|
cat $INFILE > $OUTFILE
|
|
|
|
</pre>
|
|
</code>
|
|
</blockquote>
|
|
|
|
<p>Hopefully this gives you something to think about and to play with
|
|
until the next article. If you're interested in more hints about bash
|
|
(or other stuff I've written about), please take a look at <a
|
|
href="http://tbr.nailed.org/">my home page</a>. If you've got
|
|
questions or comments, please <a
|
|
href="mailto:pate@tbr.nailed.org">drop me a line</a>.
|
|
|
|
|
|
|
|
|
|
<!-- *** BEGIN copyright *** -->
|
|
<P> <hr> <!-- P -->
|
|
<H5 ALIGN=center>
|
|
|
|
Copyright © 2000, Pat Eyler<BR>
|
|
Published in Issue 57 of <i>Linux Gazette</i>, September 2000</H5>
|
|
<!-- *** END copyright *** -->
|
|
|
|
<!--startcut ==========================================================-->
|
|
<HR><P>
|
|
<CENTER>
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="correa4.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue57/eyler.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="eyler2.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
</CENTER>
|
|
</BODY></HTML>
|
|
<!--endcut ============================================================-->
|