-2

I need to extract some variables and functions from a zsh script into a bash script. Is there any way to do this? What I've tried (some are embarrassingly wrong, but covering everything):

. /script/path.zsh (zsh-isms exist, so it fails)

exec zsh
. /script/path.zsh
exec bash
zsh << 'EOF'
. /script/path.zsh
EOF
chsh -s zsh
. /script/path.zsh
chsh -s bash

This thread is the closest I've found. Unfortunately, I have too many items to import for that to be feasible, and neither script is anywhere near a polyglot. However, the functions and variables that I need to import are polyglots.

4
  • 3
    You can't, any more than you can load a Perl library into a Python interpreter. To source a file is to run it in your already-invoked interpreter. If the interpreter doesn't know how to read the file, it can't possibly run it. Commented Apr 18, 2022 at 12:40
  • Now, there are plenty of ways to extract variables with simple types (by having zsh source the script and then write the variables in a format bash can read), but if the functions contain zshisms, you're simply out-of-luck -- bash can't run a function that's written only for zsh. Commented Apr 18, 2022 at 12:41
  • ...what workarounds, if any, exist depends on the details of those functions -- if the function is self-contained enough that it doesn't need to be able to change shell state, f/e, you can have bash start a copy of zsh that sources the file, runs a function, and exits every time it needs the function run; but if the function's invocation is supposed to change bash's state, then you need to do the work to translate those state changes, and it quickly gets into a place where it would just be easier to rewrite the script at hand. Commented Apr 18, 2022 at 12:44
  • 1
    IMO, your best approach would be to separate the "common" functions and variables into a separate file that both bash and zsh can source. Commented Apr 18, 2022 at 13:40

1 Answer 1

0

You can "scrape" the zsh source file for what you need, then execute the code in bash using eval. Here's an example for doing this for a few functions:

File script.zsh:

test1() {
    echo "Hello from test1"
}

test2() {
    echo $((1 + $1))
}

File script.sh (bash):

# Specify source script and functions
source_filename="script.zsh"
source_functions=" \
    test1          \
    test2          \
"

# Perform "sourcing"
function_definitions="$(python -B -c "
import re
with open('${source_filename}', mode='r') as file:
    content = file.read()
for func in '${source_functions}'.split():
    print(re.search(func + r'\(\).*?\n}', content, flags=re.DOTALL).group())
" )"
eval "${function_definitions}"

# Try out test functions
test1                         # Hello from test1
n=5
echo "$n + 1 is $(test2 $n)"  # 5 + 1 is 6

Run the bash script and it will make use of the functions test1 and test2 defined in the zsh script:

bash script.sh

The above makes use of Python, specifically its re module. It simply looks for character sequences of the form funcname(), and assumes that the function ends at the first }. So it's not very general, but works if you write your functions in this manner.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.