Discussion:
[Help-bash] A string handling question please.
George R Goffe
2018-07-24 00:10:00 UTC
Permalink
Hi,

I'm writing a function that will build a string based on the args passed to it and ultimately be executed as a bash command or commands linked via pipes. I'm a little confused and need some help please.

For example:

invoke doit() with args a b c d e: doit $a $b $c $d $e

generate command" xx=$(history | $a | $b | $c -z | $d | $e) and then execute $xx.

The history command produces nothing. Bash or maybe me is confused about what's happening vs what I want to happen.

Any hints/tips/suggestions/clues are welcome.

Regards,

George...
Pierre Gaston
2018-07-24 06:19:21 UTC
Permalink
Post by George R Goffe
Hi,
I'm writing a function that will build a string based on the args passed
to it and ultimately be executed as a bash command or commands linked via
pipes. I'm a little confused and need some help please.
invoke doit() with args a b c d e: doit $a $b $c $d $e
generate command" xx=$(history | $a | $b | $c -z | $d | $e) and then execute $xx.
The history command produces nothing. Bash or maybe me is confused about
what's happening vs what I want to happen.
Any hints/tips/suggestions/clues are welcome.
Regards,
George...
I'll make some assumptions as to what you want exactly, but maybe this will
help:

First, just to be sure the function must be defined in your current shell,
so in a file you are sourcing, your .bashrc etc.. (see
http://mywiki.wooledge.org/BashFAQ/060)

Then I assume the variable contains commands that are correctly quoted, eg:

a='grep -v "foo\$"'
b='sed "s/^/b:"'

a quick and simple way to check this is that if you type

echo "$a"

it should print a command that you can copy paste as is.
(I suggest reading http://mywiki.wooledge.org/Quotes )

Now, just expanding the commands will not be enough they will not be
executed, you will need to evaluate them:

doit () { eval xx="\$(history | "$1" | "$2")" ;}

Note: the quotes are important here as well

if you want something that takes a variable number of arguments:
doit ()
{
local pipe arg;
for arg in "$@";
do
pipe="$pipe | $arg";
done;
eval xx="\$(history ${pipe+"$pipe"})"
}

a='sed "s/^/filtered:/"'
b="grep doit"
doit "$a" "$b"
echo "$xx"
Pierre Gaston
2018-07-24 06:23:06 UTC
Permalink
Post by Pierre Gaston
Post by George R Goffe
Hi,
I'm writing a function that will build a string based on the args passed
to it and ultimately be executed as a bash command or commands linked via
pipes. I'm a little confused and need some help please.
invoke doit() with args a b c d e: doit $a $b $c $d $e
generate command" xx=$(history | $a | $b | $c -z | $d | $e) and then execute $xx.
The history command produces nothing. Bash or maybe me is confused about
what's happening vs what I want to happen.
Any hints/tips/suggestions/clues are welcome.
Regards,
George...
I'll make some assumptions as to what you want exactly, but maybe this
First, just to be sure the function must be defined in your current shell,
so in a file you are sourcing, your .bashrc etc.. (see
http://mywiki.wooledge.org/BashFAQ/060)
a='grep -v "foo\$"'
b='sed "s/^/b:"'
a quick and simple way to check this is that if you type
echo "$a"
it should print a command that you can copy paste as is.
(I suggest reading http://mywiki.wooledge.org/Quotes )
Now, just expanding the commands will not be enough they will not be
doit () { eval xx="\$(history | "$1" | "$2")" ;}
Note: the quotes are important here as well
doit ()
{
local pipe arg;
do
pipe="$pipe | $arg";
done;
eval xx="\$(history ${pipe+"$pipe"})"
}
a='sed "s/^/filtered:/"'
b="grep doit"
doit "$a" "$b"
echo "$xx"
I forgot to mention http://mywiki.wooledge.org/BashFAQ/048 about eval
Greg Wooledge
2018-07-25 13:52:06 UTC
Permalink
Post by George R Goffe
I'm writing a function that will build a string based on the args passed to it and ultimately be executed as a bash command or commands linked via pipes.
"I'm trying to put a command in a variable, but the complex cases always fail!"
https://mywiki.wooledge.org/BashFAQ/050
Post by George R Goffe
invoke doit() with args a b c d e: doit $a $b $c $d $e
https://mywiki.wooledge.org/Quotes
Post by George R Goffe
generate command" xx=$(history | $a | $b | $c -z | $d | $e) and then execute $xx.
What on earth is the actual goal you're trying to achieve here? Why
is there a hard-coded "-z" argument to the third command in the list?

At first glance I would have thought the goal was "take a list of simple
commands and run them all as a pipeline", but the hard-coded -z destroys
that notion. The hard-coded -z is just so incredibly WEIRD that the only
goal I can think of is "I know the third command in the list is going to
be sort and I know the sort command will need -z", but then if you know
this much a priori about the list, why not simply write the entire list
as a single function and then call it?

If the goal really is "take a list of commands and run them all as a
pipeline", then I suggest not doing it in bash. Bash is not well suited
for passing lists of lists around (each simple command being a list of
its own, because it has arguments, and then the outer list being the
list of all the simple commands). Other languages like Tcl are better
for that.

Loading...