Mã lai trong các kịch bản shell. Chia sẻ biến


10

Câu trả lời này thảo luận về cách chạy đoạn mã Python nhiều dòng từ dòng lệnh trong thiết bị đầu cuối. Tôi nhận thấy rằng câu trả lời hoạt động rất tốt trong các kịch bản shell, ngay cả với thụt lề lồng nhau, rất hay, ví dụ:

#!/bin/bash
some_text="Hello world"
echo $some_text

cat <<EOF | python -
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF

in:

0 
hello
hello
1
hello
hello
2
hello
hello

Tuy nhiên, tôi gặp khó khăn khi chia sẻ các biến giữa tập lệnh shell và đoạn mã Python.

  1. Làm cách nào tôi có thể thu thập đầu ra của chỉ mục python trong tập lệnh bash? (ví dụ trong một biến như $output).

  2. Làm cách nào tôi có thể chuyển một biến bash (ví dụ $some_text) cho tập lệnh Python?


1
Bạn có thể làm python - <<EOFthay thế.

jftr imo đây là phong cách xấu và bạn nên cố gắng tránh điều đó
Ulrich Dangel

1
Tại sao thẻ / zsh?
Stéphane Chazelas

Câu trả lời:


12

Bắt một biến thành Python

Vì (khi EOFđiểm đánh dấu không được trích dẫn) thay thế biến xảy ra trước khi văn bản được chuyển từ pythonđầu vào tiêu chuẩn sang đầu vào tiêu chuẩn, bạn có thể ném biến ngay trong tập lệnh.

python - <<EOF
some_text = "$some_text"
EOF

Nếu some_texttest, trăn sẽ thấy some_text = "test". Tuy nhiên, lưu ý rằng nó có thể được coi là một lỗ hổng tiêm mã. Nếu some_text"; import os; os.system("evil-command"); x = ", ví dụ, python sẽ thấy:

some_text = ""; import os; os.system("evil-command"); x = ""

và chạy lệnh ác đó.

Nếu bạn muốn có thể kéo mã Python của mình ngay vào tập lệnh mà không cần sửa đổi gì, bạn có thể xuất biến của mình.

export some_text

và sử dụng os.environđể lấy nó.

some_text = os.environ['some_text']

Đó là một cách tiếp cận an toàn hơn / an toàn hơn.


Nhận đầu ra từ Python

Bạn có thể sử dụng thay thế lệnh để thu thập đầu ra của tập lệnh.

output=$(
python - <<EOF
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)

(lưu ý rằng tất cả các ký tự dòng mới được loại bỏ)


Điều này có vẻ tuyệt vời. Khi bạn nói "You could also pass the variable to the script as an argument", bạn sẽ làm thế nào khi xem xét rằng tập lệnh Python được nhúng trong tập lệnh shell?
Amelio Vazquez-Reina

Xin lỗi, tôi đã quên điều đó trong một giây. Tôi đã loại bỏ giải pháp đó và thêm một giải pháp tốt hơn.

Hãy cẩn thận làm thế nào bạn đặt tên cho dấu hiệu di truyền. Khi nó không được trích dẫn như trong ví dụ của bạn, việc mở rộng shell sẽ xảy ra trong chuỗi heredoc. Ví dụ, nếu mã python của bạn chỉ bao gồm print '$SHELL', đầu ra sẽ là /bin/bashhoặc bất cứ thứ gì vỏ của bạn xảy ra. Nếu bạn thay đổi dòng đầu tiên thành python - <<'END', đầu ra sẽ là $SHELL. Nếu bạn đang sao chép và dán mã hiện có để nhúng vào tập lệnh bash, bạn gần như chắc chắn không muốn thay thế shell - bạn muốn mã chạy giống như khi nó không được nhúng trong tập lệnh bash, phải không?
Chris Johnson

8

Vấn đề với cách tiếp cận của bạn là tập lệnh python nhúng không còn có quyền truy cập vào stdin gốc (vì stdin của nó là ... chính nó).

Nếu đó là một vấn đề bạn có thể viết:

python -c '
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
'

Hoặc nếu tập lệnh python có thể chứa dấu ngoặc đơn:

python -c "$(cat << 'EOF'
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)"

Hoặc là:

python <(cat << 'EOF'
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)

6

Sử dụng dấu gạch ngang làm tên tệp:

ruby - a b <<'END'
puts ARGV.join(",")
END

python - a b <<'END'
import sys
print ",".join(sys.argv[1:])
END

Tôi không biết liệu sys.argv[1:]có đúng cách để làm điều này trong Python không. Đối với -e / -c, bạn có thể chỉ định kết thúc đối số bằng -:

set -- -a -b -c
ruby -e 'puts ARGV.join(",")' -- "$@"
python -c 'import sys; print ",".join(sys.argv[2:])' -- "$@"

Chụp đầu ra và chuyển hướng STDERR:

x=$(ruby <<'END' 2> /dev/null
puts "a"
abort "b"
END
)

2

1) Bạn có thể viết các phép gán biến cho một tệp bằng python và sau đó lấy nguồn đó trong tập lệnh bash của bạn.

2) Vì từ của bạn (EOF) không được trích dẫn, tất cả các dòng của tài liệu ở đây phải chịu sự mở rộng tham số. Bạn có thể sử dụng điều này để truyền công cụ cho tập lệnh python.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.