0

I have a shell function (in .bashrc) which creates a temp file, executes the arguments (including all sequence of pipelines), redirects it to a temp file and then open it in VS Code.

I invoke the shell function as

Temp "ls | nl"

In the follwoing code, I tried to make it work. I break the entire string with IFS as a space, store it in an array. Now I want to execute the entire sequence of pipelines and redirect the final stdout to the temp file. How can I achieve this.? I know that for loop won't work here. But I want to print the entire array.

Temp() {
    a="$(mktemp --suffix=.md "/tmp/$1-$(GetFilename "$2")-XXX")"
    IFS=' ' read -r -a Array <<< "$1"
    nArray=${#Array[@]} # Size of array
    for ((i=0; i<nArray; i=i+1)); do

    done
    #"${@}" > "$a"
    code -r "$a"
}

In the interactive terminal session the following works:

cat <<EOF
$(ls | nl)
EOF

So, I tried Heredoc, instead of the for loop inside the function

cat > "$a" <<EOF
$($1)
EOF

But this puts quotes around | and thus fails.

The above would work, if we could remove the quotes somehow.


This also doesn't work

cat > "$a" <<EOF
$(echo $1 | sed "s/'//g")
EOF

1 Answer 1

2

If you want a function to execute a shell command given as an argument, you'll need to use eval on the string, e.g. this prints FOO:

eval_arg() {
    eval "$1"
}
eval_arg "echo foo |tr a-z A-Z"

Just expanding "$1" won't do, since shell grammar like pipes, quotes and redirections aren't processed after parameter expansions. Splitting the first argument to an array or to $@ doesn't really change this.


So, $(ls | nl) has a verbatim pipe character, which is processed in the shell, but in $($1), any special characters within the value of $1 aren't processed (apart from word splitting and globs). There are no quotes in play here.

As for that last example, $(echo $1 | sed "s/'//g") splits the value of $1 on whitespace (word splitting with the default IFS), then joins the words with spaces (echo), passes that as input to sed which removes any single quotes there.

Hence:

$ set -- "'foo  bar'"
$ $(echo $1 | sed "s/'//g")
foo bar 

The outer quotes in the set command are processed by the shell, while the inner quotes are part of the value. Note that just set -- 'foo bar' would not result in $1 containing any quotes, the only quotes here would be removed as part of the normal shell processing.

0

You must log in to answer this question.

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