skip to Main Content

The following index_of function doesn’t work for all cases:

#!/bin/bash

index_of() {
    local string="$1"
    local search_string="$2"
    
    local prefix=${string/${search_string}*/}
    
    local index=${#prefix}
     
    if [[ index -eq ${#string} ]];
    then
        index=-1
    fi
    
    printf "%s" "$index"
}

a='#[hello] world'

b=$(index_of "$a" "world")
echo "A: $b"

b=$(index_of "$a" "hello")
echo "B: $b"

b=$(index_of "$a" "#[hello]")
echo "C: $b"

Here is the output:

A: 9
B: 2
C: -1

The A and B is correct, but the C is incorrect.

The C should be 0 instead of -1.

What’s wrong in the index_of function and how to fix the C index?

2

Answers


  1. #!/bin/bash
    
    index_of() {
        local string="$1"
        local search_string="$2"
    
        local prefix=${string/${search_string}*/}
    
        local index=${#prefix}
    
        if [[ $index -eq ${#string} ]];
        then
            index=-1
        fi
    
        printf "%s" "$index"
    }
    
    a='#[hello] world'
    
    b=$(index_of "$a" "world")
    echo "A: $b"
    
    b=$(index_of "$a" "hello")
    echo "B: $b"
    
    b=$(index_of "$a" "#[hello]")
    echo "C: $b"
    

    result

    A: 9
    B: 2
    C: 0
    
    Login or Signup to reply.
  2. When using parameter expansion in the pattern part of constructs like ${param/pattern/repl}, quote the parameter expansion to remove the special meaning of any shell pattern metacharacters that may exist in the parameter.

    Here’s a slightly different implementation of your index_of function. In case the length of the second argument is zero, the index shall be zero. At the end, a return value is provided to indicate success or failure. "$2" is quoted in ${1/"$2"*/} so it is treated literally, not as a shell pattern.

    #! /bin/bash -
    
    index_of () {
        local idx pfx
    
        pfx=${1/"$2"*/}
        idx=$((${#1} == ${#pfx} ? -!!${#2} : ${#pfx}))
    
        printf '%sn' "$idx"
        return "$((idx < 0))"
    }
    
    for str in world hello '#[hello]'; do
        index_of '#[hello] world' "$str"
    done
    

    output:

    9
    2
    0
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search