Tag Archives: bash

Bash array tutorial

Like some of other advanced program language, Bash also has Array data structures. There are some basic array tutorials can be found in The Ultimate Bash Array Tutorial with 15 Examples

Syntax:
declare -a Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');

Also the keyword declare -a can be omitted.

There are still some tips in daily really shell scripts:

Declare Array more simple

Array is created automatically when a variable is used in the format like,

name[index]=value

Length of the Array vs Length of the nth Element

We can get the length of an array using the special parameter called $#.

${#arrayname[@]} gives you the length of the whole array.

But, if the @ sign replace with nth of the element (>=1), then gives you the length of the nth Element in an array. Also if omit the [nth], the nth Defaults to the first element of the array.

echo ${#Unix[@]} # Number of elements in the array. => 7
echo ${#Unix}  # Number of characters in the first element located at index 1. i.e Debian => 6
echo ${#Unix[2]} # Echo the 2th element 'Red hat' length => 7 

Difference between @ and * when referencing array values

This Bash guide says:

If the index number is @ or *, all members of an array are referenced.

LIST=(1 2 3)
for i in "${LIST[@]}"; do
  echo "example.$i "
done

Gives: example.1 example.2 example.3 (desired result).

But if use ${LIST[*]}, The loop will get example.1 2 3 instead.

when using echo, @ and * actually do give the same results like,

echo ${LIST[@]}
echo ${LIST[*]}

both echos get the desired result: 1 2 3

The difference is subtle; $* creates one argument, while $@ will expand into separate arguments, so:

for i in "${LIST[@]}"

will deal with the list (print it) as multiple variables

but

for i in "${LIST[*]}"

will deal with the list as one variable.

Read Content of a File into an Array

You can load the content of the file line by line into an array by cat, example like,

$ cat loadcontent.sh

filecontent=( `cat "logfile" `)
for t in "${filecontent[@]}"; do
  echo $t
done
echo "Read file content!"

Also you can use [read][3] for more duplex through for loop. such as Reading Columns like,

var="one two three"
read -r col1 col2 col3 <<< "$var"
printf "col1: %s, col2: %s, col3 %s\n" "$col1" "$col2" "$col3"

Dump first column value of each line

while read -r -a line; do
  i=$((${#line[@]} - 1));
  [ $i -eq -1 ] || echo "${line["$i"]}";
done <~/.ssh/config

Parse predefine config in ~/.ssh/config like,

$ cat ~/.ssh/config
#def USER_NAME apps
#def HOST_PREFIX 10.200.51
Host *
    ControlMaster auto
    ControlPath ~/.ssh/master-%r@%h:%p
...
while read -r x k v; do
  if [ "$x" == "#def" ]; then
    echo "{$k/$v}";
  fi;
done <~/.ssh/config

In the above example, the k/v prefixing with #def has printed through for loop.

Upgrade Bash to 4+ on OS X and Use GNU Instead of BSD Command

Install latest bash

Install by brew for OS X user brew install bash

Compiling bash with source code: http://ftp.gnu.org/gnu/bash/

  • Add /usr/local/bin/bash to /etc/shells
  • Change the default shell with chsh -s /usr/local/bin/bash
  • To see your current version of bash do the following: echo $BASH_VERSION

Install and Use GNU Command Line Tools on Mac OS X

If you are moving onto Mac OS X from Linux, you would probably find out that the command line tools shipped with Mac OS X are not as powerful and easy to use as the tools in Linux. The reason is that Mac OS X uses the BSD version command line tools, which are different from the Linux version, while they are both compliant with POSIX standards.

  • Install the GNU Command Line Tools

    Get the latest GNU Coreutils and install to /usr/local/coreutils/

    wget http://ftpmirror.gnu.org/coreutils/coreutils-8.22.tar.xz
    tar xzf coreutils-8.22.tar.xz && cd coreutils-8.22
    ./configure --prefix=/usr/local/coreutils-8.22
    sudo make install
    sudo ln -sf /usr/local/coreutils-8.22 /usr/local/coreutils
    
  • Enable GNU coreutils, add coreutils bin folder to $PATH

    add script to .profile or .bash_profile

    export PATH="/usr/local/coreutils/bin:$PATH"
    

Links:

SVN commond tips

SVN undo files added

In Subversion, to cancel an svn add example_folder command before committing to the repository, do not use svn delete or svn remove or made-up stuff like undo or cancel.

Use the svn revert command:

svn revert -R example_folder

How to display a specific user’s commits in svn log?

svn log [SVNPath] --search <USERNAME> -l <LIMIT>

For example:

svn log . --search allex -l 100

Revert changes from specific commit / Undoing Changes

Attempt to revert some changes by a specific commit version: 854

svn merge -r 854:853 l3toks.dtx

Note: 注意版本号之间的顺序,这个叫反向合并 (reverse merger)

or

svn merge -c -854 l3toks.dtx

The two commands are equivalent.