pass array value to subshell ?

pass array value to subshell ?

Post by Gerald Jone » Fri, 19 Dec 2003 10:12:44



I wrote the following function in order to browse my .bash_history file and
select a previously issued command:

selhist()
{

   (( $# < 1 )) && echo "Usage: selhist [command]" && return 1
   c=0
   grep $1 .bash_history | sort | uniq | while read line
   do
      c=$(( $c + 1 ))
      cmd[$c]=$line
      echo -e [$c] ${cmd[$c]}
   done | less
   echo -n "enter number of desired command: "
   read answer
   # execute user's choice
   ${cmd[$answer]}

Quote:}

I expect the final line to execute the command that the user wants.  No dice.
Then I read that command substitution spawns a subshell.  If thats the case
with ${cmd[$answer]}, then how can I pass $answer to the cmd array?  If it's
not possible, then should I use awk or something similar? How?

Thanks for any insight,
Gerald

 
 
 

pass array value to subshell ?

Post by Chris F.A. Johnso » Fri, 19 Dec 2003 15:40:16



> I wrote the following function in order to browse my .bash_history file and
> select a previously issued command:

> selhist()
> {

>    (( $# < 1 )) && echo "Usage: selhist [command]" && return 1
>    c=0
>    grep $1 .bash_history | sort | uniq |

{
 while read line

Quote:>    do
>       c=$(( $c + 1 ))
>       cmd[$c]=$line
>       echo -e [$c] ${cmd[$c]}
>    done | less
>    echo -n "enter number of desired command: "
>    read answer
>    # execute user's choice
>    ${cmd[$answer]}

  eval "${cmd[$answer]}"

Quote:}
> }

> I expect the final line to execute the command that the user wants.  No dice.
> Then I read that command substitution spawns a subshell.  If thats the case
> with ${cmd[$answer]}, then how can I pass $answer to the cmd array?  If it's
> not possible, then should I use awk or something similar? How?

   Or:

TAB=$'\t'
selhist()
{
   [ $# -lt 1 ] &&  { echo "Usage: selhist [command]"; return 1; }
   oldIFS=$IFS
   IFS=$'\n'
   cmd=(  "" `grep -w $1 $HOME/.bash_history | sort | uniq | pr -tn` "" )
   IFS=$oldIFS


   read answer
   # execute user's choice
   eval "${cmd[$answer]#*$TAB}"

Quote:}

   Note that the -w option to grep and the -F option to less are not
   universal.

--
    Chris F.A. Johnson                        http://cfaj.freeshell.org
    ===================================================================
    My code (if any) in this post is copyright 2003, Chris F.A. Johnson
    and may be copied under the terms of the GNU General Public License

 
 
 

pass array value to subshell ?

Post by William Par » Fri, 19 Dec 2003 16:10:06



> I wrote the following function in order to browse my .bash_history
> file and select a previously issued command:

> selhist()
> {

>    (( $# < 1 )) && echo "Usage: selhist [command]" && return 1
>    c=0
>    grep $1 .bash_history | sort | uniq | while read line
>    do
>       c=$(( $c + 1 ))
>       cmd[$c]=$line
>       echo -e [$c] ${cmd[$c]}
>    done | less
>    echo -n "enter number of desired command: "
>    read answer
>    # execute user's choice
>    ${cmd[$answer]}

> }

> I expect the final line to execute the command that the user wants.
> No dice.  Then I read that command substitution spawns a subshell.  If
> thats the case with ${cmd[$answer]}, then how can I pass $answer to
> the cmd array?  If it's not possible, then should I use awk or
> something similar? How?

You are not doing any command substitution.  Commands in pipe (ie. grep,
sort, uniq, while) run in subshells.  So, 'cmd[]' array will not be
available outside the while-loop.

However, what you want to do can be done through command history search.
    man bash (^R in emacs-mode, / in vi-mode)

--

Linux solution for data management and processing.

 
 
 

pass array value to subshell ?

Post by Gerald Jone » Wed, 24 Dec 2003 07:18:10



Quote:> TAB=$'\t'
[...]
>    oldIFS=$IFS
[...]
>    IFS=$'\n'
[...]
>    eval "${cmd[$answer]#*$TAB}"

Can you explain whats going on with TAB and IFS?  Why is this neccessary for it
to work?

Thanks,
Gerald

 
 
 

pass array value to subshell ?

Post by Chris F.A. Johnso » Sun, 28 Dec 2003 07:01:21




>> TAB=$'\t'
> [...]
>>    oldIFS=$IFS
> [...]
>>    IFS=$'\n'
> [...]
>>    eval "${cmd[$answer]#*$TAB}"

> Can you explain whats going on with TAB and IFS?  Why is this neccessary for it
> to work?

    $TAB is a literal TAB; $NL is a literal newline.

    Setting IFS (internal field separator) to a newline prevents word
    splitting on spaces and tabs, and allows assigning each line,
    instead of each word, to an array element.

    TAB is the separator between the line number and the text in the
    output of "pr -tn"; "${cmd[$answer]#*$TAB}" returns the portion of
    the variable after the TAB, i.e., the command to be executed.

--
    Chris F.A. Johnson                        http://cfaj.freeshell.org
    ===================================================================
    My code (if any) in this post is copyright 2003, Chris F.A. Johnson
    and may be copied under the terms of the GNU General Public License