0

I have a shell script (I use GNU bash 4.4.20 on Ubuntu 18.04) with a list of commands I often run, e.g.:

sudo program1 $1 foo arg1
sudo program2 $1 foo arg2
sudo program1 $1 bar arg3
sudo program2 $1 bar arg4

I'd like to grep for select lines in this script and run them. For example if I'd like to run lines 3 and 4 above with $1 set to "some_value", I was thinking something like this would work:

set some_value; grep bar my_shell_script.sh | xargs -L1

I think my problems are 1) I'm not sure how to use xargs if the command itself is embedded in the input and 2) I'm not sure how to set $1 in the context of xargs if it's receiving its input from grep.

nonagon
  • 593

1 Answers1

1

In the lines of what you tried:

grep bar my_shell_script.sh | bash -- /dev/stdin some_value

Note in the above code the stdin of the new bash comes from grep. If the new bash runs a command that also reads from stdin then the command will read from grep. To be on the safe side or if you explicitly want to use the stdin for something else, use this syntax:

bash <(grep bar my_shell_script.sh) my-bash some_value
# or
bash -c "$(grep bar my_shell_script.sh)" my-bash some_value

Or if you want the code to be executed in the current shell:

. <(grep bar my_shell_script.sh) some_value

Notes:

  • Don't you want to quote $1 in your file?
  • Process substitution (<(…)) is not portable. You tagged , Bash supports it. Command substitution ($(…)) is portable but it will fail with argument list too long if the output from grep is too long.
  • my-bash is explained here: What is the second sh in sh -c 'some shell code' sh? (the explanation is in the context of sh -c/bash -c).
  • /dev/stdin may or may not exist in your OS.
  • This answer does not discuss (in)sanity of running code by filtering a "script" with grep. In this matter I assume you know what you want.