Skip to main content

3. String operations

  1. Length of the string: ${#parameter}

    foo="This string is long."
    echo "'$foo' is ${#foo} characters long."

    However, ${#@} and ${#*} give the number of the positional parameters.

  2. Extract a substring:
    ${parameter:offset}
    ${parameter:offset:length}

    echo ${foo:5}
    echo ${foo:5:6}
    echo ${foo: -5}
    echo ${foo: -5:2}

    Notice that a space is needed before the - in order to avoid confusion with a default value.

  3. Remove text from the beginning and from the end:
    ${parameter#pattern}
    ${parameter##pattern}
    ${parameter%pattern}
    ${parameter%%pattern}

    foo=file.txt.zip
    echo ${foo#*.}
    echo ${foo##*.}
    echo ${foo%.*}
    echo ${foo%%.*}
  4. Replace:
    ${parameter/pattern/string}
    ${parameter//pattern/string}
    ${parameter/#pattern/string}
    ${parameter/%pattern/string}

    foo=XYZ.XYZ.XYZ
    echo ${foo/XYZ/ABC}
    echo ${foo//XYZ/ABC}
    echo ${foo/%XYZ/ABC}
    echo ${foo/#XYZ/ABC}

    If the replacement is omitted, then the matched pattern will be deleted.

    echo ${foo/XYZ}
    echo ${foo//XYZ}
    echo ${foo/%XYZ}
    echo ${foo/#XYZ}
  5. Let's modify the previous longest-word example to use ${#j} instead of $(echo -n "$j" | wc -c) for getting the length of a word:

    diff -u longest-word3.sh longest-word2.sh
    diff -u longest-word3.sh longest-word2.sh
    --- longest-word2.sh 2023-06-28 01:48:25.000000000 +0000
    +++ longest-word3.sh 2023-09-30 16:13:27.942258976 +0000
    @@ -7,7 +7,7 @@
    max_word=
    max_len=0
    for j in $(strings "$i"); do
    - len="$(echo -n "$j" | wc -c)"
    + len="${#j}"
    if (( len > max_len )); then
    max_len="$len"
    max_word="$j"
    vim longest-word3.sh
    longest-word3.sh
    #!/bin/bash

    # longest-word2: find longest string in a file

    for i; do
    if [[ -r "$i" ]]; then
    max_word=
    max_len=0
    for j in $(strings "$i"); do
    len="${#j}"
    if (( len > max_len )); then
    max_len="$len"
    max_word="$j"
    fi
    done
    echo "$i: '$max_word' ($max_len characters)"
    fi
    done
    ls -l /usr/bin > dirlist-usr-bin.txt
    ./longest-word3.sh dirlist-usr-bin.txt

    It is not only simpler, but also more efficient:

    time ./longest-word3.sh dirlist-usr-bin.txt
    time ./longest-word2.sh dirlist-usr-bin.txt
  6. Case conversion:

    foo=ABCD
    echo ${foo,}
    echo ${foo,,}
    foo=abcd
    echo ${foo^}
    echo ${foo^^}

    We can also declare a variable to keep only uppercase or lowercase content:

    declare -u foo
    foo=aBcD
    echo $foo
    declare -l foo
    foo=aBcD
    echo $foo
    unset foo
    foo=aBcD
    echo $foo
Loading asciinema cast...