在一行命令行中执行多行语句
我使用带有 -c
的 Python 来执行单行循环,即:
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
如何解决此问题?
对我来说,将其作为一行代码很重要,这样我就可以将其包含在 中生成文件。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
你可以做
或者没有管道:
或者
或者 SilentGhost 的答案< /a> 或 Crast 的回答。
You could do
Or without pipes:
Or
Or SilentGhost's answer or Crast's answer.
这种风格也可以在 makefile 中使用(事实上它经常被使用)。
或者使用硬制表符:
在上述情况下,前导制表符也被删除(并且可以实现一些结构化的外观)。
除了 EOF 之外,还可以在行首处放置未出现在此处文档中的任何标记字(另请参阅 bash 手册页中的此处文档或 这里)。
This style can be used in makefiles too (and in fact it is used quite often).
Or with hard tabs:
In above case, leading TAB characters are removed too (and some structured outlook can be achieved).
Instead of EOF can stand any marker word not appearing in the here document at a beginning of a line (see also here documents in the bash man page or here).
问题实际上并不在于 import 语句。它是在 for 循环之前的任何内容。或者更具体地说,出现在内联块之前的任何内容。
例如,这些都有效:
如果 import 作为语句是一个问题,那么这会起作用,但事实并非如此:
对于您非常基本的示例,您可以将其重写为:
但是,lambda 只能执行表达式,而不是语句或多个语句,所以你可能仍然无法做你想做的事情。然而,在生成器表达式、列表理解、lambda、sys.stdout.write、内置“map”和一些创造性的字符串插值之间,您可以做一些强大的单行代码。
问题是,您想要走多远,在什么时候最好编写一个小的
.py
文件来代替您的 makefile 执行?The issue is not actually with the import statement. It's with anything being before the for loop. Or more specifically, anything appearing before an inlined block.
For example, these all work:
If import being a statement were an issue, this would work, but it doesn't:
For your very basic example, you could rewrite it as this:
However, lambdas can only execute expressions, not statements or multiple statements, so you may still be unable to do the thing you want to do. However, between generator expressions, list comprehension, lambdas, sys.stdout.write, the "map" builtin, and some creative string interpolation, you can do some powerful one-liners.
The question is, how far do you want to go, and at what point is it not better to write a small
.py
file which your makefile executes instead?- 为了使这个答案也适用于 Python 3.x,
print
被称为函数:在 3.x 中,仅print('foo')
有效,而 2.x 也接受print 'foo'
。- 有关包括 Windows 的跨平台视角,请参阅 kxr 的有用答案。
在
bash
、ksh
或zsh
中:使用 ANSI C 引用字符串 (
$'...'
),它允许使用\n
来表示在字符串传递给python
之前扩展为实际换行符的换行符:-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print("rob")'请注意
\n< /code> 在
import
和for
语句之间实现换行。要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:
请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print(sys.argv[1])' "$name"请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print("rob")'请注意
\n< /code> 在
import
和for
语句之间实现换行。要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:
请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print(sys.argv[1])'如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print("rob")'请注意
\n< /code> 在
import
和for
语句之间实现换行。要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:
请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print(sys.argv[1])' "$name"请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print("rob")'请注意
\n< /code> 在
import
和for
语句之间实现换行。要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:
请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print("rob")'-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print("rob")'请注意
\n< /code> 在
import
和for
语句之间实现换行。要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:
请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print(sys.argv[1])' "$name"请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
import sys\nfor r in range(10): print("rob")'请注意
\n< /code> 在
import
和for
语句之间实现换行。要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:
请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。
要安全地使用
$'...'
字符串:\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由$'...'
扩展(请参阅man printf
了解支持的转义)'
实例转义为\'
。如果您必须保持POSIX兼容:
将
printf
与命令一起使用替换:要安全地使用此类字符串:
\
实例。\
序列 - 例如本例中的\n
,但也有常见的嫌疑人,例如\t
、< code>\r、\b
- 由printf
扩展(有关支持的转义序列,请参阅man printf
)。将单引号字符串传递给
printf %b
,并将嵌入的单引号转义为'\''
(原文如此)。使用单引号可以保护字符串的内容不被 shell 解释。
也就是说,对于短 Python 脚本(如本例所示),您可以使用双引号字符串将shell 变量值合并到脚本中 -只要您意识到相关的陷阱(请参阅下一点);例如,shell 将
$HOME
扩展为当前用户的主目录。在以下命令中:python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
但是,通常首选的方法是通过参数从 shell 传递值,并在 Python 中通过 sys.argv 访问它们;与上述命令等效的是:
python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
虽然使用双引号字符串更方便 - 它允许您使用嵌入式单引号(未转义)和嵌入式双引号作为
\"
- 它还使字符串受到shell的解释,这可能是也可能不是$
和`
;源代码中不适合 shell 的字符可能会导致语法错误或意外更改字符串。\
对双引号字符串的处理可能会造成妨碍;例如,要让Python生成文字输出ro\b
,您必须将ro\\b
传递给它;使用'...'
shell 字符串和双倍\
实例,我们得到:python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
相比之下,这无法按照
"..."
shell 字符串的预期工作:python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !!错误:“rs”
shell 将
"\b"
和"\\b"
都解释为文字\b
,这需要令人眼花缭乱的达到预期效果的额外\
实例数量:python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"
通过
stdin 传递代码
而不是-c
:注意:我在这里重点关注单行解决方案; xorho 的答案展示了如何使用多行here-document - 但是请务必引用分隔符;例如,
<<'EOF'
,除非您明确希望 shell 预先扩展字符串(这带有上面提到的注意事项)。在
中bash
、ksh
或zsh
:组合 ANSI C 引用字符串 (
$'...'
),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<...
):-
明确告诉python
从 stdin 读取(默认情况下)。在这种情况下,
-
是可选的,但如果您还想将参数传递给脚本,则确实需要它来消除脚本文件名中的参数的歧义:如果您必须保留POSIX 兼容:
如上所述使用
printf
,但使用管道,以便通过 stdin 传递其输出:带有参数:
- To make this answer work with Python 3.x as well,
print
is called as a function: in 3.x, onlyprint('foo')
works, whereas 2.x also acceptsprint 'foo'
.- For a cross-platform perspective that includes Windows, see kxr's helpful answer.
In
bash
,ksh
, orzsh
:Use an ANSI C-quoted string (
$'...'
), which allows using\n
to represent newlines that are expanded to actual newlines before the string is passed topython
:-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print("rob")'Note the
\n
between theimport
andfor
statements to effect a line break.To pass shell-variable values to such a command, it is safest to use arguments and access them via
sys.argv
inside the Python script:See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print(sys.argv[1])' "$name"See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print("rob")'Note the
\n
between theimport
andfor
statements to effect a line break.To pass shell-variable values to such a command, it is safest to use arguments and access them via
sys.argv
inside the Python script:See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print(sys.argv[1])'If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print("rob")'Note the
\n
between theimport
andfor
statements to effect a line break.To pass shell-variable values to such a command, it is safest to use arguments and access them via
sys.argv
inside the Python script:See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print(sys.argv[1])' "$name"See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print("rob")'Note the
\n
between theimport
andfor
statements to effect a line break.To pass shell-variable values to such a command, it is safest to use arguments and access them via
sys.argv
inside the Python script:See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print("rob")'-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print("rob")'Note the
\n
between theimport
andfor
statements to effect a line break.To pass shell-variable values to such a command, it is safest to use arguments and access them via
sys.argv
inside the Python script:See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print(sys.argv[1])' "$name"See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
import sys\nfor r in range(10): print("rob")'Note the
\n
between theimport
andfor
statements to effect a line break.To pass shell-variable values to such a command, it is safest to use arguments and access them via
sys.argv
inside the Python script:See below for a discussion of the pros and cons of using an (escape sequence-preprocessed) double-quoted command string with embedded shell-variable references.
To work safely with
$'...'
strings:\
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$'...'
(seeman printf
for the supported escapes)'
instances as\'
.If you must remain POSIX-compliant:
Use
printf
with a command substitution:To work safely with this type of string:
\
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 byprintf
(seeman 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.\
processing in double-quoted strings can get in the way; for instance, to get Python to produce literal outputro\b
, you must passro\\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')")"
To pass the code via
stdin
rather than-c
:Note: I'm focusing on single-line solutions here; xorho's answer shows how to use a multi-line here-document - be sure to quote the delimiter, however; e.g.,
<<'EOF'
, unless you explicitly want the shell to expand the string up front (which comes with the caveats noted above).In
bash
,ksh
, orzsh
:Combine an ANSI C-quoted string (
$'...'
) with a here-string (<<<...
):-
tellspython
explicitly to read from stdin (which it does by default).-
is optional in this case, but if you also want to pass arguments to the scripts, you do need it to disambiguate the argument from a script filename:If you must remain POSIX-compliant:
Use
printf
as above, but with a pipeline so as to pass its output via stdin:With an argument:
你的问题是由这样一个事实造成的:Python 语句由
;
分隔,只允许是“小语句”,它们都是单行语句。从 Python 文档 中的语法文件:复合语句不能通过分号与其他语句包含在同一行 - 因此使用
-c
标志执行此操作变得非常不方便。在 bash shell 环境中演示 Python 时,我发现包含复合语句非常有用。可靠地做到这一点的唯一简单方法是使用heredocs(一个posix shell)。
Heredocs
使用 heredoc (使用
< 创建;<
) 和 Python 的命令行界面选项、-
:在
<<-
之后添加-
(<<-
)可以让您使用制表符缩进(Stackoverflow 将制表符转换为空格,因此我缩进了 8 个空格来强调这一点)。前导标签将被剥离。您可以在没有选项卡的情况下仅使用
<<
来完成此操作:在
EOF
周围加上引号可以防止 参数 和 算术扩展。这使得定界符更加稳健。Bash 多行字符串
如果使用双引号,则会得到 shell 扩展:
为了避免 shell 扩展,请使用单引号:
请注意,我们需要交换 Python 中文字上的引号字符 - 我们基本上不能使用引号字符由 BASH 解释。不过,我们可以交替使用它们,就像在 Python 中一样 - 但这看起来已经很混乱了,这就是为什么我不推荐这样做:对
已接受答案(和其他答案)的批评
这不是很可读:
可读性不太好,而且在出现错误时也很难调试:
也许更具可读性,但仍然很丑陋:
如果你的 python 中有
"
你会遇到麻烦:不要滥用
map
或列表推导式来获取 for 循环:这些都是悲伤和糟糕的。不要做它们。
Your problem is created by the fact that Python statements, separated by
;
, are only allowed to be "small statements", which are all one-liners. From the grammar file in the Python docs:Compound statements can't be included on the same line with other statements via semicolons - so doing this with the
-c
flag becomes very inconvenient.When demonstrating Python while in a bash shell environment, I find it very useful to include compound statements. The only simple way of doing this reliably is with heredocs (a posix shell thing).
Heredocs
Use a heredoc (created with
<<
) and Python's command line interface option,-
:Adding the
-
after<<
(the<<-
) allows you to use tabs to indent (Stackoverflow converts tabs to spaces, so I've indented 8 spaces to emphasize this). The leading tabs will be stripped.You can do it without the tabs with just
<<
:Putting quotes around
EOF
prevents parameter and arithmetic expansion. This makes the heredoc more robust.Bash multiline strings
If you use double-quotes, you'll get shell-expansion:
To avoid shell expansion use single-quotes:
Note that we need to swap the quote characters on the literals in Python - we basically can't use quote character being interpreted by BASH. We can alternate them though, like we can in Python - but this already looks quite confusing, which is why I don't recommend this:
Critique of the accepted answer (and others)
This is not very readable:
Not very readable, and additionally difficult to debug in the case of an error:
Perhaps a bit more readable, but still quite ugly:
You'll have a bad time if you have
"
's in your python:Don't abuse
map
or list comprehensions to get for-loops:These are all sad and bad. Don't do them.
只需使用 Return 并在下一行输入:
Just use Return and type it on the next line:
工作正常。
使用“[ ]”内联 for 循环。
works fine.
Use "[ ]" to inline your for loop.
此变体最适合在 Windows 和类 Unix 系统、Python 2 和 Python 3 上的命令行上放置多行脚本,无需管道:(
到目前为止,这里看到的其他示例都没有这样做。
)在 Windows 上是:
Neat 在类 Unix 系统上的 Bash 上是:
该函数将任何多行脚本转换为可移植的单行命令:
用法:
输入是:
This variant is most portable for putting multi-line scripts on the command-line on Windows and Unix-like systems, Python 2 and Python 3, without pipes:
(None of the other examples seen here so far did so.)
Neat on Windows is:
Neat on Bash on Unix-like systems is:
This function turns any multiline-script into a portable command-one-liner:
Usage:
The input was:
问题不在于
import
语句。问题在于控制流语句不能在 Python 解释器命令中内联工作。将import
语句替换为任何其他语句,您将看到相同的问题。想一想:Python 不可能内联所有内容。它使用缩进对控制流进行分组。
The problem is not with the
import
statement. The problem is that the control flow statements don't work inlined in a Python interpreter command. Replace thatimport
statement with any other statement, and you'll see the same problem.Think about it: Python can't possibly inline everything. It uses indentation to group control-flow.
如果您的系统兼容 POSIX.2,它应该提供
printf
实用程序:If your system is POSIX.2-compliant it should supply the
printf
utility:我并不是一个真正的 Python 爱好者 - 但我曾经发现过这个语法,忘记了从哪里来的,所以我想我应该记录一下它:
如果你使用
sys.stdout.write
而不是print
(区别在于,sys.stdout.write
将参数作为函数,放在括号中 - 而print
则不然) ,那么对于一行,您可以通过反转命令和for
的顺序,删除分号,并将命令括在方括号中,即:我不知道这是怎么回事语法将在 Python 中调用:)
这些单行括号中的方括号是“列表推导式”;请注意 Python 2.7 中的这一点:
输出:
因此圆括号/圆括号中的命令被视为“生成器对象”;如果我们通过调用
next()
来“迭代”它 - 那么括号内的命令将被执行(注意输出中的“abc”):输出:
如果我们现在使用方括号 - 注意我们不需要调用 next() 来执行命令,它会在分配后立即执行;然而,后来的检查显示
a
是None
:输出:
对于方括号的情况,这并没有留下太多信息可供查找 - 但我偶然发现了这个页面我认为解释:
Python 提示和技巧 –第一版 - Python 教程 |梦想代码:
事实上,它是一个列表 -它只是它的第一个元素在执行后立即变为空:
输出:
输出:
列表推导式另外记录在 5.数据结构:5.1.4。列表推导式 — Python v2.7.4 文档,“列表推导式提供了一种创建列表的简洁方法”;想必,这就是列表的有限“可执行性”在俏皮话中发挥作用的地方。
好吧,希望我在这里没有太离题……
这是一个带有两个非嵌套 for 循环的单行命令行;两者都包含在“列表理解”方括号内:
输出:
请注意,第二个“列表”
b
现在有两个元素,因为它的 for 循环显式运行了两次;然而,在这两种情况下,sys.stdout.write()
的结果(显然)都是None
。I'm not really a big Pythoner - but I found this syntax once, forgot where from, so I thought I'd document it:
If you use
sys.stdout.write
instead ofprint
(the difference being,sys.stdout.write
takes arguments as a function, in parentheses - whereasprint
doesn't), then for a one-liner, you can get away with inverting the order of the command and thefor
, removing the semicolon, and enclosing the command in square brackets, i.e.:I have no idea how this syntax would be called in Python :)
These square brackets in one-liners are "list comprehensions"; note this in Python 2.7:
Output:
So the command in round brackets/parenthesis is seen as a "generator object"; if we "iterate" through it by calling
next()
- then the command inside the parenthesis will be executed (note the "abc" in the output):Output:
If we now use square brackets - note that we don't need to call
next()
to have the command execute, it executes immediately upon assignment; however, later inspection reveals thata
isNone
:Output:
This doesn't leave much information to look for - for the square brackets case - but I stumbled upon this page which I think explains:
Python Tips And Tricks – First Edition - Python Tutorials | Dream.In.Code:
And indeed it is a list - it's just its first element becomes none as soon as it is executed:
Output:
Output:
List comprehensions are otherwise documented in 5. Data Structures: 5.1.4. List Comprehensions — Python v2.7.4 documentation as "List comprehensions provide a concise way to create lists"; presumably, that's where the limited "executability" of lists comes into play in one-liners.
Well, hope I'm not terribly too off the mark here ...
And here is a one-liner command line with two non-nested for-loops; both enclosed within "list comprehension" square brackets:
Output:
Notice that the second "list"
b
now has two elements, since its for loop explicitly ran twice; however, the result ofsys.stdout.write()
in both cases was (apparently)None
.单/双引号
和反斜杠
无处不在:好多了:
注意:在某些系统上可执行文件
python
适用于Python 2和可能不可用。可执行文件python3
适用于 Python 3。single/double quotes
andbackslash
everywhere:Much better:
Note: On some systems executable
python
is for Python 2 and may not be available. And executablepython3
is for Python 3.使用带有三引号的 python -c :
Use
python -c
with triple quotes:我想要一个具有以下属性的解决方案:
其他答案中没有提供这两个要求,因此以下是如何在命令行上执行所有操作时读取标准输入:
I wanted a solution with the following properties:
Both requirements were not provided in the other answers, so here's how to read standard input while doing everything on the command line:
当我需要这样做时,我使用:
注意 sys.stdout.write 语句中换行符的三个反斜杠。
When I needed to do this, I used:
Note the triple backslash for the newline in the sys.stdout.write statement.
如果您不想触摸标准输入并像您一样进行模拟通过“python cmdfile.py”,您可以从 Bash shell 执行以下操作:
如您所见,它允许您使用标准输入来读取输入数据。 shell 在内部为输入命令内容创建临时文件。
If you don't want to touch standard input and simulate as if you had passed "python cmdfile.py", you can do the following from a Bash shell:
As you can see, it allows you to use standard input for reading input data. Internally the shell creates the temporary file for the input command contents.
还有一种选择。 sys.stdout.write 返回 None,这使列表保持为空:
There is one more option. sys.stdout.write returns None, which keeps the list empty: