Bash datatypes

From wikinotes

Strings

basics

firstname="luke"
lastname="skywalker"

fullname="$firstname $lastname"   # variables are expanded within '"' quotes.

# HEREDOC format
vimrc=$(cat <<-EOF
filetype off
syntax enable
set rtp+=.
EOF
)

substitution

var="hello:how:are:you"
var=${var//:/*}
echo $var

#> hello*how*are*you

slices

var="abcd"

# echo ${var:<start>:<finish>}
echo ${var:1}              #> bcd
echo ${var:0:3}            #> abc
echo ${var:0:${#var[@]}}   #> abcd

IFS

The $IFS variable (internal field separator) determines which character is used to separate items in a list. By default it is a single empty space.

You can change it, if you'd like. Some use cases:

  • iterating over stdout lines
  • iterating over $PATH entries
export PATH=/sbin:/bin:/usr/bin:/usr/local/bin
oIFS="$IFS"
IFS=":"

for item in ${PATH[@]}; do
    echo "$item"
done

IFS="$oIFS"  # restore IFS to default

Numbers

Bash does not have numeric types.

Collections

Arrays

basics

NOTE:

Arrays are 1-indexed

array=()                    # initialize empty array
array=(one two three)       # create array
array=(\
  one \
  two \
  three \
)
array+=(four)                    # append to array

array[2]="two"                   # assign array val (NOTE no dollar)
${#array[@]}                     # array length
${array[@]:3:6}                  # array slice of items 3-6
${array[*]}                      # all array entries
array=( "${array[@]/$delete}" )  # delete item from array

joined=$(printf ",%s" "${array[@]}" | cut -c 2-)  # join array by ','

concat=( 
    "${array_1[@]}"
    "${array_2[@]}"
)

[[ "${array[@]}" =~ "two" ]] && echo "two in array"  # check item in array

Shuffle an array (safe for items with spaces)

# create array
FILES=()
for f in `find .`; do; FILES+=("$f"); done

# shuffle array
SHUF_FILES=()
while read -r item; do; SHUF_FILES+=("$item"); done < <(shuf -e "${FILES[@]}")
echo ${SHUF_FILES[1]}

array from output

unsafe
newline-separated items, that do not contain spaces

my_array=( $(ls -l | tr '\n' ' ') )  # (no-spaces) multiline output to array (one entry per line)

bash

#!/usr/bin/env bash

ls -l | readarray -t my_array        # (bash-only) multiline output with spaces

zsh

#!/usr/bin/env zsh

# in zsh, you can use parameter-expansion flags ('f' here) to split on newlines
# https://zsh.sourceforge.io/Doc/Release/Expansion.html#Parameter-Expansion-Flags
# https://unix.stackexchange.com/questions/29724/how-to-properly-collect-an-array-of-lines-in-zsh

my_array=("${(f)$(ls -l)}")  # one array-item per line

Associative Arrays

# associative arrays must be declared (any of declare/local/readonly)
declare -A servers

# assignment
servers[billspc]="10.1.0.2"
servers[profoak]="10.1.0.5"

# usage
echo ${servers[billspc]}