我使用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中。


当前回答

还有一个选择。sys.stdout.write返回None,保持列表为空:

cat somefile.log|python -c "import sys;[line for line in sys.stdin if sys.stdout.write(line*2)]"

其他回答

-使用Python 3使这个答案生效。X以及,print被称为一个函数:在3。X,只有print('foo')可以工作,而2。X也接受打印'foo'。 -关于跨平台(包括Windows)的观点,请参阅kxr的有用答案。

在bash、ksh或zsh中:

使用ANSI c引号字符串($'…'),它允许使用\n表示在字符串传递给python之前展开为实际换行的换行:

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

注意import语句和for语句之间的\n可以产生换行。

要将shell变量值传递给这样的命令,最安全的方法是使用参数并通过sys. js访问它们。Python脚本中的argv:

name='rob' # value to pass to the Python script
python -c $'import sys\nfor r in range(10): print(sys.argv[1])' "$name"

关于使用(转义序列预处理)双引号命令字符串与嵌入的shell变量引用的优缺点,请参见下面的讨论。

使用$'安全工作…的字符串:

在原始源代码中使用双实例。 \<char>序列-例如本例中的\n,但也有常见的嫌疑,例如\t, \r, \b -被$'…’(参见man printf了解支持的转义) 转义“实例为\”。


如果你必须保持posix兼容:

使用printf替换命令:

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

要安全地使用这种类型的字符串:

Double \ instances in your original source code. \<char> sequences - such as \n in this case, but also the usual suspects such as \t, \r, \b - are expanded by printf (see man printf for the supported escape sequences). Pass a single-quoted string to printf %b and escape embedded single quotes as '\'' (sic). Using single quotes protects the string's contents from interpretation by the shell. That said, for short Python scripts (as in this case) you can use a double-quoted string to incorporate shell variable values into your scripts - as long as you're aware of the associated pitfalls (see next point); e.g., the shell expands $HOME to the current user's home dir. in the following command: python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")" However, the generally preferred approach is to pass values from the shell via arguments, and access them via sys.argv in Python; the equivalent of the above command is: python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME" While using a double-quoted string is more convenient - it allows you to use embedded single quotes unescaped and embedded double quotes as \" - it also makes the string subject to interpretation by the shell, which may or may not be the intent; $ and ` characters in your source code that are not meant for the shell may cause a syntax error or alter the string unexpectedly. Additionally, the shell's own \ processing in double-quoted strings can get in the way; for instance, to get Python to produce literal output ro\b, you must pass ro\\b to it; with a '...' shell string and doubled \ instances, we get: python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs' By contrast, this does not work as intended with a "..." shell string: python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs' The shell interprets both "\b" and "\\b" as literal \b, requiring a dizzying number of additional \ instances to achieve the desired effect: python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"


通过stdin而不是-c来传递代码:

注意:这里我关注的是单线解决方案;Xorho的回答展示了如何使用多行here-document -但一定要引用分隔符;例如,<<'EOF',除非你明确地想让shell在前面展开字符串(这与上面提到的注意事项一起出现)。


在bash、ksh或zsh中:

将ANSI c引号字符串($'…')与here字符串(<<<…)组合:

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

-告诉python显式地从stdin读取(默认情况下)。 -在这种情况下是可选的,但如果你还想向脚本传递参数,你确实需要它来消除脚本文件名的参数歧义:

python - 'rob' <<<$'import sys\nfor r in range(10): print(sys.argv[1])'

如果你必须保持posix兼容:

像上面一样使用printf,但是使用管道,以便通过stdin传递输出:

printf %b 'import sys\nfor r in range(10): print("rob")' | python

带论点:

printf %b 'import sys\nfor r in range(10): print(sys.argv[1])' | python - 'rob'

单/双引号和反斜杠无处不在:

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

更好:

python -c '
import sys
for i in range(10):
  print("bob")
'

注意:在某些系统上,可执行python适用于python 2,可能不可用。可执行的python3是针对python3的。

使用python -c加三引号:

python -c """
import os
os.system('pwd')
os.system('ls -l')
print('Hello, World!')
for _ in range(5):
    print(_)
"""

问题并不在于import语句。它是在for循环之前的任何东西。或者更具体地说,出现在内联块之前的任何东西。

例如,这些都是有效的:

python -c "import sys; print 'rob'"
python -c "import sys; sys.stdout.write('rob\n')"

如果import是一个语句是一个问题,这将工作,但它不是:

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

对于最基本的例子,你可以这样写:

python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"

然而,lambdas只能执行表达式,而不能执行语句或多条语句,因此您可能仍然无法执行您想要执行的事情。然而,在生成器表达式、列表理解、lambdas、sys.stdout之间。写,“映射”内置,和一些创造性的字符串插值,你可以做一些强大的一行程序。

问题是,您想要走多远,以及在什么情况下编写一个小的.py文件而让makefile执行不是更好?

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

工作很好。

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