我使用Python和-c来执行一行循环,即:

python -c "for r in range(10): print 'rob'"

这很好。但是,如果我在for循环之前导入一个模块,就会得到一个语法错误:

python -c "import sys; for r in range(10): print 'rob'"

  File "<string>", line 1
    import sys; for r in range(10): print 'rob'
              ^
SyntaxError: invalid syntax

如何解决这个问题?

对我来说,将它作为一行程序很重要,这样我就可以将它包含在Makefile中。


当前回答

这个变体在Windows和类unix系统(Python 2和Python 3)的命令行上放置多行脚本是最可移植的,没有管道:

python -c "exec(\"import sys \nfor r in range(10): print('rob') \")"

(到目前为止,这里看到的其他例子都没有这样做。)

Windows上的Neat是:

python -c exec"""import sys \nfor r in range(10): print 'rob' """
python -c exec("""import sys \nfor r in range(10): print('rob') """)

类unix系统上Bash的Neat是:

python -c $'import sys \nfor r in range(10): print("rob")'

该函数将任何多行脚本转换为可移植的命令行:

def py2cmdline(script):
    exs = 'exec(%r)' % re.sub('\r\n|\r', '\n', script.rstrip())
    print('python -c "%s"' % exs.replace('"', r'\"'))

用法:

>>> py2cmdline(getcliptext())
python -c "exec('print \'AA\tA\'\ntry:\n for i in 1, 2, 3:\n  print i / 0\nexcept:\n print \"\"\"longer\nmessage\"\"\"')"

输入是:

print 'AA    A'
try:
 for i in 1, 2, 3:
  print i / 0
except:
 print """longer
message"""

其他回答

问题不在于import语句。问题是控制流语句不能内联在Python解释器命令中工作。将该import语句替换为任何其他语句,您将看到相同的问题。

想想看:Python不可能内联所有东西。它使用缩进来分组控制流。

如果你不想触摸标准输入并模拟你已经传递了"python cmdfile.py",你可以在Bash shell中执行以下操作:

python <(printf "word=raw_input('Enter word: ')\nimport sys\nfor i in range(5):\n    print(word)")

如您所见,它允许您使用标准输入读取输入数据。shell在内部为输入命令内容创建临时文件。

python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

工作很好。

使用“[]”内联for循环。

你可以这样做

echo -e "import sys\nfor r in range(10): print 'rob'" | python

或没有管道:

python -c "exec(\"import sys\nfor r in range(10): print 'rob'\")"

Or

(echo "import sys" ; echo "for r in range(10): print 'rob'") | python

或者沉默鬼的回答,或者卡斯特的回答。

我不是一个真正的大python -但我发现这个语法一次,忘记从哪里来的,所以我想我应该记录它:

如果你使用sys.stdout.write而不是print(区别在于,sys.stdout.write接受圆括号内的函数参数-而print不接受),那么对于一行程序,你可以将命令和for的顺序颠倒,删除分号,并将命令括在方括号中,即:

python -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

我不知道这个语法在Python中是如何调用的:)


一行中的方括号是“列表推导式”;在Python 2.7中注意这一点:

STR=abc
echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); print a"

输出:

<generator object <genexpr> at 0xb771461c>

因此,圆括号/圆括号中的命令被视为“生成器对象”;如果我们通过调用next()来“迭代”它,那么括号内的命令将被执行(注意输出中的“abc”):

echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); a.next() ; print a"

输出:

abc
<generator object <genexpr> at 0xb777b734>

如果我们现在使用方括号——注意我们不需要调用next()来执行命令,它会在赋值时立即执行;然而,后来的检查发现a是None:

echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; print a"

输出:

abc
[None]

这并没有留下太多的信息去寻找——对于方括号的情况——但我偶然发现了这一页,我认为它解释了:

Python技巧和技巧-第一版- Python教程| Dream.In.Code:

If you recall, the standard format of a single line generator is a kind of one line 'for' loop inside brackets. This will produce a 'one-shot' iterable object which is an object you can iterate over in only one direction and which you can't re-use once you reach the end. A 'list comprehension' looks almost the same as a regular one-line generator, except that the regular brackets - ( ) - are replaced by square brackets - [ ]. The major advantage of alist comprehension is that produces a 'list', rather than a 'one-shot' iterable object, so that you can go back and forth through it, add elements, sort, etc.

实际上它是一个列表——只是它的第一个元素在执行时变成了none:

echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin].__class__"

输出:

abc
<type 'list'>

echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin][0]"

输出:

abc
None

列表推导式在5中另有说明。数据结构:5.1.4。列表推导式——Python v2.7.4文档“列表推导式提供了一种简洁的创建列表的方法”;据推测,这就是列表的有限“可执行性”在一行程序中发挥作用的地方。

好吧,希望我没有说得太离谱……

这里有一个单行命令行,包含两个非嵌套的for循环;两者都包含在“列表理解”方括号内:

echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; b=[sys.stdout.write(str(x)) for x in range(2)] ; print a ; print b"

输出:

abc
01[None]
[None, None]

注意,第二个“列表”b现在有两个元素,因为它的for循环显式地运行了两次;然而,sys.stdout.write()在这两种情况下的结果(显然)都是None。