user556068 user556068 - 2 months ago 6
Bash Question

echo elements of an array outputs nothing

This is basically a continuation of this question. The following script prompts the user for a search string and then returns a numbered list of

history
commands containing that string.

#!/bin/bash

read -p 'Search history for? ' string

i=0
OLDIFS=$IFS
IFS=$'\n'

HISTFILE="$HOME/.bash_history"
history -r
arr=( "$(history | grep -i "$string" | cut -c8-)" )

for item in ${arr[@]}
do
echo "$(( i++ )) $item"
done


I wanted to extend this by then asking the user to select one of the commands listed

read -p 'select a command or type /q to quit ' n
if [[ $n = '/q' ]]; then
exit
else
for cmd in ${arr[$n]}
do
echo "$cmd"
done
fi
IFS=$OLDIFS


However this returns nothing every time. I've used this same sort of selection method before with success. Why doesn't this work in this particular scenario?

Answer

Your array arr has only one element 0 because you are assigning the quoted result of the command. Try using the index 0. And also try this (no quotes):

arr=( $(history | grep -i "$string" | cut -c8-) )

Now that the reason is clear, the solution should be something like:

IFS=$'\n' read -d '' -a arr <<<"$(history | grep -i "$string" | cut -c8-)"

Or (bash > 4.0):

readarray -t arr <<<"$(history | grep -i "$string" | cut -c8-)"

Why the change? To split the result on newlines and to avoid the expansion of '*' and others from "Pathname expansion".


Also, you do not need a loop to print one item, use this instead:

read -p 'select a command or type /q to quit ' n
[[ $n = '/q' ]] && exit
echo "command for $n -- ${arr[n]}"
IFS=$OLDIFS