这基本上是this question的延续。以下脚本提示用户输入搜索字符串,然后返回包含该字符串的history
命令的编号列表。
#!/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
我想通过要求用户选择列出的命令之一来扩展它
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
但是每次都不会返回任何内容。在成功之前,我已经使用过这种相同的选择方法。为什么在这种特殊情况下这不起作用?
答案 0 :(得分:1)
也许你想使用内置的选择:
#!/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-)
select choice in $arr; do echo "your choice is $choice"; break; done
IFS=$OLDIFS
输出:
...
33) kill -l
#? 33
your choice is kill -l
答案 1 :(得分:1)
您的数组arr
只有一个元素0
,因为您正在分配命令的引用结果。尝试使用索引0.并尝试这个(没有引号):
arr=( $(history | grep -i "$string" | cut -c8-) )
现在原因很清楚,解决方案应该是:
IFS=$'\n' read -d '' -a arr <<<"$(history | grep -i "$string" | cut -c8-)"
或(bash&gt; 4.0):
readarray -t arr <<<"$(history | grep -i "$string" | cut -c8-)"
为什么要改变?将结果拆分为换行符并避免扩展&#39; *&#39;以及其他来自&#34;路径名扩展&#34;。
此外,您不需要循环来打印一个项目,而是使用它:
read -p 'select a command or type /q to quit ' n
[[ $n = '/q' ]] && exit
echo "command for $n -- ${arr[n]}"
IFS=$OLDIFS