Series: What is REST?, A Basic REST API, Paging, Search, Security, Token, OpenID.
The basic concepts of REST APIs:
Slides: What is REST?.
Code: poemtube on github.
Series: What is REST?, A Basic REST API, Paging, Search, Security, Token, OpenID.
The basic concepts of REST APIs:
Slides: What is REST?.
Code: poemtube on github.
Bash arrays are a lot like Bash Associative Arrays, but with numbers as keys.
Here’s a quick reference.
$ declare -a MYARR # Create an array $ MYARR[3]=foo # Put a value into an array $ echo ${MYARR[3]} # Get a value out of an array foo $ echo MYARR[3] # WRONG MYARR[0] $ echo $MYARR[3]] # WRONG [3]
$ declare -a MYARR # Explicitly declare $ MYARR[3]=foo # Or this line implicitly makes it an array $ MYARR[4]=bar # Can add values one by one
$ declare -a MYARR=(a b c) # Initialise all at once $ echo ${MYARR[0]} a $ echo ${MYARR[1]} b $ echo ${MYARR[2]} c
$ declare -a MYARR # Or declare separately $ MYARR=(a b c) # Then initialise $ echo ${MYARR[0]} a $ echo ${MYARR[1]} b $ echo ${MYARR[2]} c
$ declare -a MYARR=(a b c) $ MYARR=("${MYARR[@]}" d) # Add an element $ echo ${MYARR[@]} a b c d $ declare -a MYARR2=(e f g) $ MYARR=("${MYARR[@]}" "${MYARR2[@]}") # Concatenate arrays $ echo ${MYARR[@]} a b c d e f g
$ declare -a MYARR $ MYARR[3]=foo $ echo ${MYARR[0]} # Unassigned values are empty $ echo ${MYARR[4]} # Unassigned values are empty $ MYARR[seven]=bar # A text index is treated as 0 $ echo ${MYARR[0]} bar $ echo ${MYARR[seven]} # A text index is treated as 0 bar
$ K=3 $ MYARR[$K]=baz # Variables containing numbers work like numbers $ echo ${MYARR[$K]} baz $ echo ${MYARR[3]} # Obviously the value is accessible via the actual index baz $ K=foo $ MYARR[$K]=bash # Variables containing text are treated as 0 $ echo ${MYARR[0]} bash
$ declare -a MYARR=(a b c) $ echo ${#MYARR[@]} # Length of an array 3 $ echo $#MYARR[@] # WRONG 0MYARR[@] $ echo ${#MYARR} # WRONG 1
$ MYARR[7]=x $ echo ${#MYARR[@]} # Only existing indices count in the length 4
$ declare -a MYARR=(a bb ccc) $ echo ${#MYARR[0]} # Length of an individual element 1 $ echo ${#MYARR[1]} 2 $ echo ${#MYARR[2]} 3
$ declare -a MYARR=("a 1" b c)
$ # Loop through array values
$ for V in "${MYARR[@]}"; do echo $V; done
a 1
b
c
$ for V in ${MYARR[@]}; do echo $V; done #WRONG
a
1
b
c
$ echo "${!MYARR[@]}" # Print all indices - quoted, but quotes removed by echo 0 1 2 $ echo "${MYARR[@]}" # Print all values - quoted, but quotes removed by echo a 1 b c
$ declare -a MYARR $ MYARR[3]=x $ echo ${MYARR[3]} x $ unset MYARR $ declare -a MYARR $ echo ${MYARR[3]}
$ MYARR[2]=foo
$ echo ${MYARR[2]}
foo
$ unset ${MYARR[2]} # WRONG
$ echo ${MYARR[2]}
foo
$ unset MYARR[2] # To delete from an array, use "unset" with similar syntax to assigning
$ echo ${MYARR[2]}
$ MYARR[3]=quux
$ echo ${MYARR[3]}
quux
$ K=3
$ unset MYARR[$K] # Can unset using a variable for the key too
$ echo ${MYARR[3]}
$ declare -a MYARR=(a b c d e f) $ MYARR=("${MYARR[@]:0:3}" "${MYARR[@]:4}") # Remove element 3, leaving no gap $ echo ${MYARR[@]}
$ declare -a MYARR=(a b c d e f g) $ echo ${MYARR[@]:2:3} # Extract a sub-array c d e
$ declare -a MYARR=(a b c d e f g) $ echo ${MYARR[@]/d/FOO} # Replace elements that match a b c FOO e f g
$ unset MYARR $ function createmap() { MYARR[5]=bar; } # Implicit creation puts it in the global scope $ echo ${MYARR[5]} $ createmap $ echo ${MYARR[5]} bar
$ unset MYARR $ function createmaplocal() { declare -a MYARR; MYARR[3]=bar; } # Explicit creation puts it in the local scope $ echo ${MYARR[3]} $ createmaplocal $ echo ${MYARR[3]}
In a previous post I outlined how to use if:set and unless:set to execute tasks conditionally in Ant 1.9.1.
Unfortunately, this does not work with macrodefs. When I try to execute a macrodef conditionally like this:
<project xmlns:if="ant:if" xmlns:unless="ant:unless" default="build" > <macrodef name="mymacro"> <sequential> <echo message="inside mymacro"/> </sequential> </macrodef> <target name="build"> <mymacro if:set="doit"/> </target> </project>
When I set the “doit” property and run like this, it fails:
$ ant -Ddoit=true Buildfile: build.xml build: BUILD FAILED build.xml:14: Unknown attribute [ant:if:if:set] Total time: 0 seconds
It looks to me like this is a bug: the if:set attribute is getting passed into the macro, which is complaining that it doesn’t expect an attribute with that name. (If you try to create an attribute with that name, you’ll find that “if:set” is an illegal name…)
However, there is a workaround. You can wrap the call to your macrodef in a <sequential> tag:
<project xmlns:if="ant:if" xmlns:unless="ant:unless" default="build" > <macrodef name="mymacro"> <sequential> <echo message="inside mymacro"/> </sequential> </macrodef> <target name="build"> <sequential if:set="doit"> <mymacro/> </sequential> </target> </project>
And now it works!
$ ant -Ddoit=true Buildfile: build.xml build: [echo] inside mymacro BUILD SUCCESSFUL Total time: 0 seconds
$ ant Buildfile: build.xml build: BUILD SUCCESSFUL Total time: 0 seconds
Conditional execution even when calling a macrodef. Enjoy.
I’m not sure anyone except me is still struggling on with using Ant, but just in case, here is a nice thing.
In Ant 1.9.1 they added a useful feature: instead of needing to use the <if> tag and similar from ant-contrib, you can conditionally execute “any” task.
(In fact, this appears to mean “any task except a macrodef” – see my post Using if:set, unless:set etc. with macrodefs in Ant.)
You need to add these namespaces at the top of your project:
<project xmlns:if="ant:if" xmlns:unless="ant:unless" >
and then make any task conditional by adding one of these attributes:
if:set if:true if:blank unless:set unless:true unless:blank
if:set and unless:set take a property name and run the task if it is set at all (or unless it is set at all).
<mytask if:set="property.name" other_attrs="" .../>
Where mytask is the name of any ordinary Ant task like echo, jar etc.
(Note there is no ${} around the property name for if:set.)
if:true and unless:true take a value and run the task if it is true (or unless it is true), so they need to be used like this:
<mytask if:true="${property}" other_attrs="" .../>
(Note the ${} here, but not above.)
Similarly, if:blank and unless:blank take a value and run the task if it is blank (or unless it is blank), e.g.:
<mytask if:blank="${property}" other_attrs="" .../>
NOTE: The example in the documentation is wrong (at this time, 2013-09-13) – it uses the property name, but this does not work – you must surround it with ${} to get its value.
The properties can be specified in your build file as normal, or supplied on the command line to ant with -Dproperty.name=value.
Here’s an example of using set:
build.xml:
<project xmlns:if="ant:if" xmlns:unless="ant:unless" default="build" > <property name="setinxml" value="true"/> <target name="build"> <echo if:set="setinxml" message="if:set=setinxml"/> <echo unless:set="setinxml" message="unless:set=setinxml"/> <echo if:set="notset" message="if:set=notset"/> <echo unless:set="notset" message="unless:set=notset"/> <echo if:set="setincmd" message="if:set=setincmd"/> <echo unless:set="setincmd" message="unless:set=setincmd"/> </target> </project>
And here’s the output:
$ ant -version Apache Ant(TM) version 1.9.2 compiled on July 8 2013 $ ant -Dsetincmd=true Buildfile: build.xml build: [echo] if:set=setinxml [echo] unless:set=notset [echo] if:set=setincmd BUILD SUCCESSFUL Total time: 0 seconds
The documentation for this, such as it is, is here: If And Unless.
I have recently got quite excited about Vim (the text editor), so here is a video showing you the basics. I use it because I enjoy learning it.
Slides: Vim for Fun.