bash shell script Part.1 入門

前言

順便紀錄一下雷點
reference: NTU csie NASA

Bash

!/bin/env bash

赴值

name="WildfootW" # no white space near "="

command

files=`ls -la`
files=$(ls -la)

use double quotes when referencing

stackoverflow
echo "I am at $(pwd)" # I am at /home/wildfoot-vm
echo 'I am at $(pwd)' # I am at $(pwd)
var="/* Foobar is free software */"
echo "$var" # /* Foobar is free software */
echo $var   # /bin /boot /cdrom /dev /etc...

參數

echo $#         # number of args
echo $0         # command itself
echo $1, $2, $3 # N-th args

數字

a=1          ; echo $a    # 1
b=$((2))     ; echo $b    # 2
c=$a+$b      ; echo $c    # 1+2
d=$(($a+$b)) ; echo $d    # 3

迴圈

for var in 1 3 2 4 5; do
    printf "$var "
done # 1 3 2 4 5 %
for var in {-1..5}; do
    printf " $var"
done # -1 0 1 2 3 4 5%
max=6
for var in $(seq 0 $max); do
    printf " $var"
done # 0 1 2 3 4 5 6%

判斷式

reference:
Linux Academy blog
Ryans Tutorials
unary operator expected

if [[ $aug1 == "and" ]]; # double quote
if [ -n "$1" ] && [ -s "$1" ]; then
    echo "This file is useful."
else
    echo "This file is not useful."
fi
! EXPRESSIONThe EXPRESSION is false.
-n STRINGThe length of STRING is greater than zero.
-z STRINGThe lengh of STRING is zero (ie it is empty).
STRING1 = STRING2STRING1 is equal to STRING2
STRING1 != STRING2STRING1 is not equal to STRING2
STRING =~ patternregular expression
INT1 -eq INT2INTEGER1 is numerically equal to INTEGER2
INT1 -gt INT2INTEGER1 is numerically greater than INTEGER2
INT1 -lt INT2INTEGER1 is numerically less than INTEGER2
test "001" =   "1" ; echo $?  # 1
test "001" -eq "1" ; echo $?  # 0
-d FILEFILE exists and is a directory.
-e FILEFILE exists.
-s FILEFILE exists and it’s size is greater than zero (ie. it is not empty).
-r FILEFILE exists and the read permission is granted.
-w FILEFILE exists and the write permission is granted.
-x FILEFILE exists and the execute permission is granted.

陣列

reference: linuxconfig

declare -a index_array;
index_array=(foo bar) ; echo ${index_array[@]} # foo bar
index_array[0]=baz    ; echo ${index_array[@]} # baz bar
index_array+=(foo qux); echo ${index_array[@]} # baz bar foo qux
unset index_array[1]  ; echo ${index_array[@]} # baz foo qux
echo "The array contains ${#index_array[@]} elements" # 3
declare -A assoc_array;
assoc_array[foobar]="baz"          ; echo ${assoc_array[@]} # baz
assoc_array+=([foo]=bar [baz]=qux) ; echo ${assoc_array[@]} # qux bar baz
unset assoc_array[foo]             ; echo ${assoc_array[@]} # qux baz

函式

reference: Linuxize

pass array as paramenters: stackoverflow

#!/usr/bin/env bash
# Array should be the last argument and only one array can be passed
function copyFiles() {
    local msg="$1"   # Save first argument in a variable
    shift            # Shift all arguments to the left (original $1 gets lost)
    local arr=("$@") # Rebuild the array with rest of arguments
    for i in "${arr[@]}"; do
        echo "$msg $i"
    done
}
array=("one" "two" "three")
copyFiles "Copying" "${array[@]}"
#!/bin/bash -u
# ==============================================================================
# Description
# -----------
# Show the content of an array by displaying each element separated by a
# vertical bar (|).
#
# Arg Description
# --- -----------
# 1   The array
# ==============================================================================
show_array()
{
    declare -a arr=("${@}")
    declare -i len=${#arr[@]}
    # Show passed array
    for ((n = 0; n < len; n++))
    do
        echo -en "|${arr[$n]}"
    done
    echo "|"
}

# ==============================================================================
# Description
# -----------
# This function takes two arrays as arguments together with their sizes and a
# name of an array which should be created and returned from this function.
#
# Arg Description
# --- -----------
# 1   Length of first array
# 2   First array
# 3   Length of second array
# 4   Second array
# 5   Name of returned array
# ==============================================================================
array_demo()
{
    declare -a argv=("${@}")                           # All arguments in one big array
    declare -i len_1=${argv[0]}                        # Length of first array passad
    declare -a arr_1=("${argv[@]:1:$len_1}")           # First array
    declare -i len_2=${argv[(len_1 + 1)]}              # Length of second array passad
    declare -a arr_2=("${argv[@]:(len_1 + 2):$len_2}") # Second array
    declare -i totlen=${#argv[@]}                      # Length of argv array (len_1+len_2+2)
    declare __ret_array_name=${argv[(totlen - 1)]}     # Name of array to be returned

    # Show passed arrays
    echo -en "Array 1: "; show_array "${arr_1[@]}"
    echo -en "Array 2: "; show_array "${arr_2[@]}"

    # Create array to be returned with given name (by concatenating passed arrays in opposite order)
    eval ${__ret_array_name}='("${arr_2[@]}" "${arr_1[@]}")'
}

########################
##### Demo program #####
########################
declare -a array_1=(Only 1 word @ the time)                                       # 6 elements
declare -a array_2=("Space separated words," sometimes using "string paretheses") # 4 elements
declare -a my_out # Will contain output from array_demo()

# A: Length of array_1
# B: First array, not necessary with string parentheses here
# C: Length of array_2
# D: Second array, necessary with string parentheses here
# E: Name of array that should be returned from function.
#          A              B             C              D               E
array_demo ${#array_1[@]} ${array_1[@]} ${#array_2[@]} "${array_2[@]}" my_out

# Show that array_demo really returned specified array in my_out:
echo -en "Returns: "; show_array "${my_out[@]}"
#!/usr/bin/env bash
# pass the array as a reference
function copyFiles {
   local -n arr=$1
   for i in "${arr[@]}"; do
      echo "$i"
   done
}
array=("one" "two" "three")
copyFiles array

Leave a Reply

Your email address will not be published. Required fields are marked *