パラメータの中間にEOFがあるのはなぜですか?

パラメータの中間にEOFがあるのはなぜですか?

import osbashまたはbashfrom sys import stdoutに新しいPythonインタプリタを作成し、モジュールをインポートするように指示するように小さなbash関数を作成したいと思います。

後者のfrom関数は次のとおりです。

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

私がこう呼んだら:

$ 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
>>> 

のバイトはfrom sys次のとおりです。

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

EOFはありませんが、PythonインタプリタはEOFを読むのと同じように動作します。ストリームの末尾に改行文字があり、これは予想される現象です。

from完全なPythonモジュールをインポートする姉妹は次のとおりです。これは文字列を削除して処理し、存在しないモジュールで失敗して問題を解決します。

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
}

これはストリームで説明されていないEOFの問題を解決しますが、PythonがEOFを持っていると思う理由を理解したいと思います。

答え1

テーブルは中です。このスタックオーバーフローの回答(これはバッシュハッカーウィキ) さまざまな Bash 変数を拡張する方法を説明します。

あなたがやっていることは、1つpython -i -c "from $@"の引数だけを許可するpython -i -c "from sys" "import" "stdout"ので、-cコマンドを実行しますfrom sys。を使用しようとすると、$*次に展開されますpython -i -c "from sys import stdout"$IFS未設定または空白で始まると仮定)。

答え2

straceいつものように、何が起こっているのかが表示されます。

bash-4.1$ echo $$
3458

strace bash ...そして他の場所では(または関数を呼び出す方法を見つけることができます):

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

最初のシェルに戻って:

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

straceその後、シェルに戻ります。

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

したがって、実際の-c議論は拡張-c "from sys"方法に関するものです。"$@"それとも、切り捨てられたコマンドですか?python

答え3

$@要素のリスト"$1" "$2" "$3"などで二重引用符で展開されます。

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

expand sys import stdout

Pythonは、コードが一連のパラメータではなくパラメータにあると予想しています。

答え4

Straceは使用されたパラメータを表示します。ただし、処理中の内容を確認する最も簡単な方法は、printf '<%s> '各関連行の前に終端を追加することですecho(新しい行を作成するため)。

したがって、この機能は次のように変更されることがあります。

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

呼び出し時:

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

明らかに、「from sys」はPythonにパラメータとして送信されます。
これはPythonが受け取るものであり、Pythonは「from sys」に対して動作します。

関連情報