Bash datatypes: Difference between revisions

From wikinotes
No edit summary
 
(20 intermediate revisions by the same user not shown)
Line 1: Line 1:
= strings =
= Strings =
<blockquote>
<blockquote>
== basics ==
== basics ==
Line 65: Line 65:
</blockquote><!-- strings -->
</blockquote><!-- strings -->


= numbers =
= Numbers =
<blockquote>
<blockquote>
 
Bash does not have numeric types.
</blockquote><!-- numbers -->
</blockquote><!-- numbers -->


= arrays =
= Collections =
<blockquote>
== Arrays ==
<blockquote>
<blockquote>


== basics ==
=== basics ===
<blockquote>
<blockquote>
{{ NOTE |
{{ NOTE |
Line 90: Line 92:
array[2]="two"                  # assign array val (NOTE no dollar)
array[2]="two"                  # assign array val (NOTE no dollar)
${#array[@]}                    # array length
${#array[@]}                    # array length
${array[3:6]}                   # array of items 3-6
${array[@]:3:6}                 # array slice of items 3-6
${array[*]}                      # all array entries
${array[*]}                      # all array entries
array=( "${array[@]/$delete}" )  # delete item from array
array=( "${array[@]/$delete}" )  # delete item from array
Line 103: Line 105:
[[ "${array[@]}" =~ "two" ]] && echo "two in array"  # check item in array
[[ "${array[@]}" =~ "two" ]] && echo "two in array"  # check item in array
</source>
</source>
Shuffle an array (safe for items with spaces)
<syntaxhighlight lang="bash">
# 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]}
</syntaxhighlight>
</blockquote><!-- basics -->
</blockquote><!-- basics -->


== array from output ==
=== array from output ===
<blockquote>
<blockquote>
'''unsafe'''<br>
newline-separated items, that do not contain spaces
<source lang="bash">
<source lang="bash">
file_array=( $(ls -l | tr '\n' ' ') )  # save multiline output to array (one entry per line)
my_array=( $(ls -l | tr '\n' ' ') )  # (no-spaces) multiline output to array (one entry per line)
</source>
</source>
'''bash'''
<syntaxhighlight lang="bash">
#!/usr/bin/env bash
ls -l | readarray -t my_array        # (bash-only) multiline output with spaces
</syntaxhighlight>
'''zsh'''
<syntaxhighlight lang="bash">
#!/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
</syntaxhighlight>
</blockquote><!-- array from output -->
</blockquote><!-- array from output -->


=== array as return value ===
<blockquote>
<syntaxhighlight lang="bash">
#!/usr/bin/env bash
create_array() {
    local -n arr=$1            # use nameref for indirection
    arr=(one "two three" four)
}
main() {
    local my_array
    create_array my_array
    echo "${my_array[1]}"
}
main
</syntaxhighlight>
</blockquote><!-- array as return value -->
</blockquote><!-- arrays -->
</blockquote><!-- arrays -->
== Associative Arrays ==
<blockquote>
<syntaxhighlight lang="bash">
# 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]}
</syntaxhighlight>
</blockquote><!-- associative Arrays -->
</blockquote><!-- Collections -->

Latest revision as of 01:58, 17 February 2024

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

array as return value

#!/usr/bin/env bash

create_array() {
    local -n arr=$1             # use nameref for indirection
    arr=(one "two three" four)
}

main() {
    local my_array
    create_array my_array
    echo "${my_array[1]}"
}

main

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]}