2

I've looked at Quoting within $(command substitution) in Bash and still don't get what I do incorrectly (my code looks to me like "is the recommended way" from accepted answer) and how to fix it:

print_and_run(){
    echo next line: "$1"
    echo "$($1)"
}

print_and_run 'sed --in-place -- "s|fetch = +refs/\*:refs/\*|fetch = +refs/heads/*:refs/remotes/origin/*|" .git/config' 
next line: sed --in-place -- "s|fetch = +refs/\*:refs/\*|fetch = +refs/heads/*:refs/remotes/origin/*|" .git/config
sed: -e expression #1, char 1: unknown command: `"'

sed line works on its own, function print_and_run works for commands w/out quotes, e.g print_and_run 'cat ./.git/config'. TIA

P.S. btw not sure it matters: I wrote echo "$($1)" not echo $($1) to print with newlines: https://stackoverflow.com/questions/15184358/how-to-avoid-bash-command-substitution-to-remove-the-newline-character, and now I see the former looks like "is the recommended way").

1
  • you probably don't want to use echo "$(foo)", it's almost the same as just foo, except that it removes any trailing newlines from the output and then adds exactly one
    – ilkkachu
    Dec 13, 2022 at 15:38

1 Answer 1

1

You can perhaps try it in a different way:

print_and_run() {
    printf "next line:"
    printf " '%s'" "$@"
    printf "\n"

    echo "$("$@")"
}

print_and_run sed --in-place -- "s|fetch = +refs/\*:refs/\*|fetch = +refs/heads/*:refs/remotes/origin/*|" .git/config

Result:

next line: 'sed' '--in-place' '--' 's|fetch = +refs/\*:refs/\*|fetch = +refs/heads/*:refs/remotes/origin/*|' '.git/config'

In this example, the original quoting is preserved. However, things like pipes or redirections still won't work.

A completely different approach would be to rely on the shell's built in command printing:

 set -x
 sed --in-place -- "s|fetch = +refs/\*:refs/\*|fetch = +refs/heads/*:refs/remotes/origin/*|" .git/config
 set +x

It will print a line like this:

+ sed --in-place -- 's|fetch = +refs/\*:refs/\*|fetch = +refs/heads/*:refs/remotes/origin/*|' .git/config

So you don't have to implement your own print command at all, the shell already does it for you.

2
  • Nice thing will be to be able to put any command into argument and don't think about formatting, but I seriously doubt bash supports that, both of your solutions are fine for my current goals. Thanks. Are substitutions made by bash (e.g. quotes in your example) always safe to copy a line from + and be able to run it as it is? Dec 13, 2022 at 15:35
  • 1
    you probably don't want to use echo "$(foo)", it's almost the same as just foo, except that it removes any trailing newlines from the output and then adds exactly one
    – ilkkachu
    Dec 13, 2022 at 15:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .