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").

Martian2020
  • 1,167
  • 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 '22 at 15:38

1 Answers1

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.

frostschutz
  • 48,978
  • 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? – Martian2020 Dec 13 '22 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 '22 at 15:38