Neden argümanların ortasında bir EOF var?


20

Biraz bash söyleyebileceğim küçük bir bash işlevi yazmak istedim, import osya da from sys import stdoutithal edilen modülle yeni bir Python yorumlayıcısı oluşturacak.

İkinci fromişlev şöyle görünür:

from () {
    echo "from $@" | xxd
    python3 -i -c "from $@"
}

Bunu ararsam:

$ from sys import stdout
00000000: 6672 6f6d 2073 7973 2069 6d70 6f72 7420  from sys import 
00000010: 7374 646f 7574 0a                        stdout.
  File "<string>", line 1
    from sys
           ^
SyntaxError: invalid syntax
>>> 

İçinde bayt from sysolan

66 72 6f 6d 20 73 79 73 20
f  r  o  m     s  y  s    

Orada EOF yok, ancak Python yorumlayıcısı EOF okumuş gibi davranıyor. Akışın sonunda beklenen bir yeni satır var.

fromPython modülünün tamamını ithal eden kız kardeşi şöyle görünür ve ipi sterilize ederek ve işleyerek ve mevcut olmayan modüllerde başarısız olarak sorunu çözer.

import () {
  ARGS=$@
  ARGS=$(python3 -c "import re;print(', '.join(re.findall(r'([\w]+)[\s|,]*', '$ARGS')))")
  echo -ne '\0x04' | python3 -i
  python3 -c "import $ARGS" &> /dev/null
  if [ $? != 0 ]; then
    echo "sorry, junk module in list"
  else
    echo "imported $ARGS"
    python3 -i -c "import $ARGS"
  fi
}

Bu, akışta açıklanamayan bir EOF sorununu çözüyor, ancak Python'un neden bir EOF olduğunu düşündüğünü anlamak istiyorum.

Yanıtlar:


42

Bu Yığın Taşması cevabındaki tablo ( Bash Hackers Wiki'den almıştır ) farklı Bash değişkenlerinin nasıl genişletildiğini açıklar:

Yapıyorsunuz python -i -c "from $@", bu dönüşüyor python -i -c "from sys" "import" "stdout"ve -csadece tek bir argüman alıyor, bu yüzden komutu çalıştırıyor from sys. Kullanmak istersiniz $*, bu genişler python -i -c "from sys import stdout"( $IFSayarlanmamış veya bir boşlukla başlar).


2
Silme işleminiz için teşekkür ederiz, çünkü bu değerli bilgiler :)
kedi

1
Bence bu gerçekten problemi çözdüğü için kabul edilen cevap olmalı, diğeri ise sadece sorunu açıklıyor, ancak çözümler veya alternatif çözümler
sunmuyor

İyi cevap. Bu tablo aslında Bash Hackers Wiki'den geliyor. Uygun ilişkilendirmeyi ekleyebilir ve dağıtım hakkına sahip olduğunuzu doğrulayabilir misiniz?
Monica ile Hafiflik Yarışları

22

strace, her zaman olduğu gibi, neler olduğunu gösterecektir:

bash-4.1$ echo $$
3458

Ve başka bir yerde (veya strace bash ...fonksiyon çağrısının nasıl yapılacağını anlayabilirsiniz ):

bash-4.1$ strace -ff -o blah -p 3458

Ve ilk kabukta:

bash-4.1$ from sys import stdout
  File "<string>", line 1
    from sys
           ^
SyntaxError: invalid syntax
>>> 
bash-4.1$ 

Ve sonra tekrar stracekabuğa:

Process 3458 attached
Process 25224 attached
^CProcess 3458 detached
bash-4.1$ grep exec blah.*
blah.25224:execve("/usr/bin/python", ["python", "-i", "-c", "from sys", "import", "stdout"], [/* 54 vars */]) = 0

Bu nedenle, gerçek -cargüman, -c "from sys"nasıl "$@"genişletildiği veya pythonüzerinde durulan kısaltılmış bir komuttan kaynaklanmaktadır .


9

$@çift ​​tırnak işaretleri gibi bir öğe listesine genişler "$1" "$2" "$3".

#!/bin/bash
expand () {
    for string in "from $@" ; do
        echo "$string"
    done
}

expand sys import stdout

Python, kodun bir dizi bağımsız değişken değil, bir bağımsız değişken içinde olmasını bekler.


6

Python şu şekilde çağrılıyor:

execve("/usr/bin/python", ["python", "-i", "-c", "from sys", "import", "stdout"], [/* 54 vars */])

( Thrig'in cevabına bakınız ).

$@Tek bir dize olarak genişletmek için (aklı başında olduğu varsayılarak $IFS), $*çift ​​tırnak içinde kullanabilirsiniz :

python3 -i -c "from $*"

İle onaylandı strace -e execve:

execve("/usr/bin/python", ["python", "-i", "-c", "from sys import stdout"], [/* 54 vars */]) = 0

2

Strace kullanılan argümanların ne olduğunu gösterir. Ancak neyin işlendiğini görmenin en basit yöntemi, printf '<%s> 'her ilgili satırdan önce bir ve bir kapanış echo(yeni satır olarak oluşturmak için) eklemektir :

Böylece, işlev şu şekilde değiştirilebilir:

from () {
    printf '<%s> ' "from $@"; echo
    printf '<%s> ' python3 -i -c "from $@"; echo
}

Ve çağrıldığında:

$ from sys import stdout
<from sys> <import> <stdout> 
<python3> <-i> <-c> <from sys> <import> <stdout>

"Sys'den" bir argüman olarak python'a gönderildiği açıktır.
Python'un aldığı budur ve python "sys'den" etki eder.

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.