Kabuk komut dosyalarında karma kod. Değişkenleri paylaşma


10

Bu yanıt , terminaldeki komut satırından çok satırlı bir Python snippet'inin nasıl çalıştırılacağını açıklar. Cevabın kabuk komut dosyalarında, çok güzel olan iç içe girintiyle bile harika çalıştığını fark ettim, örn.

#!/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

baskılar:

0 
hello
hello
1
hello
hello
2
hello
hello

Ancak, kabuk komut dosyası ve Python snippet arasında değişkenleri paylaşmakta zorlanıyorum.

  1. Python aboneliğinin çıktısını bash betiğinde nasıl toplayabilirim? (örneğin, gibi bir değişkende $output).

  2. Bir bash değişkenini (örneğin $some_text) Python komut dosyasına nasıl iletebilirim ?


1
Bunun python - <<EOFyerine yapabilirsiniz .

jftr imo bu kötü bir stil ve bundan kaçınmaya çalışmalısınız
Ulrich Dangel

1
Neden / zsh etiketi?
Stéphane Chazelas

Yanıtlar:


12

Python'a değişken alma

EOFMetin heredoc'tan pythonstandart girdiye geçirilmeden önce ( işaretçi alıntılanmadığında) değişken değiştirme gerçekleştiği için , değişkeni komut dosyasında doğrudan atabilirsiniz.

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

Eğer some_textoldu test, piton görecekti some_text = "test". Ancak bunun kod yerleştirme güvenlik açığı olarak görülebileceğini unutmayın. Eğer some_textoldu "; import os; os.system("evil-command"); x = ", örneğin, piton görecekti:

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

ve o kötü komutu çalıştırın.

Python kodunuzu herhangi bir değişiklik yapmadan bir betiğe çekebilmek istiyorsanız değişkeninizi dışa aktarabilirsiniz.

export some_text

ve os.environalmak için kullanın .

some_text = os.environ['some_text']

Bu çok daha güvenli / daha güvenli bir yaklaşım.


Python'dan çıktı alma

Komut dosyasının çıktısını toplamak için komut ikamesini kullanabilirsiniz.

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

(sondaki tüm yeni satır karakterlerinin kaldırıldığını unutmayın)


Harika görünüyor. Söylediğinizde "You could also pass the variable to the script as an argument", Python betiğinin kabuk betiğinin içine gömülü olduğunu düşünerek bunu nasıl yapardınız?
Amelio Vazquez-Reina

Üzgünüm, bir an için unuttum. Bu çözümü çıkardım ve daha iyi bir çözüm ekledim.

Yorumlu metin işaretçisini nasıl adlandırdığınıza dikkat edin. Örneğinizdeki gibi tırnak işareti kaldırıldığında, yorumlu metin dizesinde kabuk genişletme gerçekleşir. Örneğin, python kodunuz sadece oluşursa print '$SHELL', çıktı /bin/bashveya kabuğunuz ne olursa olsun olur. İlk satırı olarak değiştirirseniz python - <<'END'çıkış olur $SHELL. Mevcut kodu bir bash betiğine gömmek için kopyalayıp yapıştırıyorsanız, neredeyse kesinlikle kabuk ikamelerini istemezsiniz - kodun bir bash betiğine gömülmediği gibi çalışmasını istersiniz, değil mi?
Chris Johnson

8

Yaklaşımınızdaki sorun, gömülü python betiğinin artık orijinal stdin'e erişimi olmamasıdır (çünkü stdin ... kendisidir).

Bu bir sorunsa şunu yazabilirsiniz:

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

Veya python betiği tek tırnak içeriyorsa:

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

Veya:

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

6

Dosya adı olarak kısa çizgi kullanın:

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

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

Bunu sys.argv[1:]Python'da yapmanın doğru yolu olup olmadığını bilmiyorum . -E / -c için argümanların sonunu - ile belirleyebilirsiniz:

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

Çıktı yakalama ve yönlendirme STDERR:

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

2

1) Python'daki bir dosyaya değişken atamaları yazabilir ve ardından bunu bash komut dosyanızda kaynaklayabilirsiniz.

2) Kelimeniz (EOF) alıntılanmadığından, bu belgedeki tüm satırlar parametre genişletmeye tabi tutulur. Python betiğine bir şeyler aktarmak için bunu kullanabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.