在一行命令行中执行多行语句

发布于 2024-08-18 00:25:05 字数 600 浏览 6 评论 0 原文

我使用带有 -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

如何解决此问题?

对我来说,将其作为一行代码很重要,这样我就可以将其包含在 中生成文件

I'm using Python with -c to execute a one-liner loop, i.e.:

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

This works fine. However, if I import a module before the for loop, I get a syntax error:

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

How can this be fixed?

It's important to me to have this as a one-liner so that I can include it in a Makefile.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

唱一曲作罢 2024-08-25 00:25:05

你可以做

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

或者没有管道:

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

或者

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

或者 SilentGhost 的答案< /a> 或 Crast 的回答

You could do

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

Or without pipes:

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

Or SilentGhost's answer or Crast's answer.

记忆で 2024-08-25 00:25:05

这种风格也可以在 makefile 中使用(事实上它经常被使用)。

python - <<EOF
import random
for r in range(3): print(random.randint(1, 42))
EOF

或者使用硬制表符:

python - <<-EOF
    import random
    for r in range(3): print(random.randint(1, 42))
EOF
# Important: Replace the indentation above w/ hard tabs.

在上述情况下,前导制表符也被删除(并且可以实现一些结构化的外观)。

除了 EOF 之外,还可以在行首处放置未出现在此处文档中的任何标记字(另请参阅 bash 手册页中的此处文档或 这里)。

This style can be used in makefiles too (and in fact it is used quite often).

python - <<EOF
import random
for r in range(3): print(random.randint(1, 42))
EOF

Or with hard tabs:

python - <<-EOF
    import random
    for r in range(3): print(random.randint(1, 42))
EOF
# Important: Replace the indentation above w/ 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).

情泪▽动烟 2024-08-25 00:25:05

问题实际上并不在于 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))"

但是,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:

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

If import being a statement were an issue, this would work, but it doesn't:

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

For your very basic example, you could rewrite it as this:

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

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?

太阳公公是暖光 2024-08-25 00:25:05


- 为了使这个答案也适用于 Python 3.xprint 被称为函数:在 3.x 中, print('foo') 有效,而 2.x 也接受 print 'foo'
- 有关包括 Windows 的跨平台视角,请参阅 kxr 的有用答案

bashkshzsh 中:

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

python -c 

请注意 \n< /code> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:

name='rob' # value to pass to the Python script
python -c 

请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \n,但也有常见的嫌疑人,例如 \t、< code>\r、\b - 由 $'...' 扩展(请参阅 man printf 了解支持的转义)
  • ' 实例转义为 \'

如果您必须保持POSIX兼容

printf命令一起使用替换

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

要安全地使用此类字符串:

  • 原始源代码中的 \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 ANSI C 引用字符串 ($'...'),带有 < a href="http://mywiki.wooledge.org/HereDocument?action=show&redirect=HereString" rel="noreferrer">这里字符串 (<<<... ):

python - <<<

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

python - 'rob' <<<

如果您必须保留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'
import sys\nfor r in range(10): print("rob")'

请注意 \n< /code> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:


请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:


请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:


请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:


请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:


请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:


请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:


请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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> 在 importfor 语句之间实现换行。

要将 shell 变量值传递给此类命令,最安全的做法是使用参数并通过 Python 脚本内的 sys.argv 访问它们:


请参阅下文,了解使用(转义序列预处理)双引号命令字符串和嵌入 shell 变量引用的优缺点的讨论。

要安全地使用 $'...' 字符串:

  • 原始源代码中的 Double \ 实例。
    • \ 序列 - 例如本例中的 \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 的字符可能会导致语法错误或意外更改字符串。

      • 此外,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 预先扩展字符串(这带有上面提到的注意事项)。


中bashkshzsh

组合 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, only print('foo') works, whereas 2.x also accepts print 'foo'.
- For a cross-platform perspective that includes Windows, see kxr's helpful answer.

In bash, ksh, or zsh:

Use an ANSI C-quoted string ($'...'), which allows using \n to represent newlines that are expanded to actual newlines before the string is passed to python:

python -c 

Note the \n between the import and for 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:

name='rob' # value to pass to the Python script
python -c 

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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:

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

To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):

python - <<<

- tells python 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:

python - 'rob' <<<

If you must remain POSIX-compliant:

Use printf as above, but with a pipeline so as to pass its output via stdin:

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

With an argument:

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

Note the \n between the import and for 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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 the import and for 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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")'

- tells python 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 the import and for 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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 the import and for 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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 the import and for 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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 the import and for 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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")'

- tells python 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 the import and for 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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 the import and for 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:

  • 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 $'...' (see man printf for the supported escapes)
  • Escape ' instances as \'.

If you must remain POSIX-compliant:

Use printf with a command substitution:


To work safely with this type of string:

  • 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')")"

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, or zsh:

Combine an ANSI C-quoted string ($'...') with a here-string (<<<...):


- tells python 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:



    
顾北清歌寒 2024-08-25 00:25:05

知道如何解决这个问题吗?

你的问题是由这样一个事实造成的:Python 语句由 ; 分隔,只允许是“小语句”,它们都是单行语句。从 Python 文档 中的语法文件:

stmt:simple_stmt |复合结构
simple_stmt:small_stmt (';'small_stmt)* [';'] NEWLINE
小_stmt:(expr_stmt | del_stmt | pass_stmt | flow_stmt |
             导入_stmt |全局_stmt |非本地_stmt |断言_stmt)

复合语句不能通过分号与其他语句包含在同一行 - 因此使用 -c 标志执行此操作变得非常不方便。

在 bash shell 环境中演示 Python 时,我发现包含复合语句非常有用。可靠地做到这一点的唯一简单方法是使用heredocs(一个posix shell)。

Heredocs

使用 heredoc (使用 < 创建;<) 和 Python 的命令行界面选项-

$ python - <<-"EOF"
        import sys                    # 1 tab indent
        for r in range(10):           # 1 tab indent
            print('rob')              # 1 tab indent and 4 spaces
EOF

<<- 之后添加 -<<-)可以让您使用制表符缩进(Stackoverflow 将制表符转换为空格,因此我缩进了 8 个空格来强调这一点)。前导标签将被剥离。

您可以在没有选项卡的情况下仅使用 << 来完成此操作:

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

EOF 周围加上引号可以防止 参数算术扩展。这使得定界符更加稳健。

Bash 多行字符串

如果使用双引号,则会得到 shell 扩展:

$ python -c "
> import sys
> for p in '$PATH'.split(':'):
>     print(p)
> "
/usr/sbin
/usr/bin
/sbin
/bin
...

为了避免 shell 扩展,请使用单引号:

$ python -c '
> import sys
> for p in "$PATH".split(":"):
>     print(p)
> '
$PATH

请注意,我们需要交换 Python 中文字上的引号字符 - 我们基本上不能使用引号字符由 BASH 解释。不过,我们可以交替使用它们,就像在 Python 中一样 - 但这看起来已经很混乱了,这就是为什么我不推荐这样做:对

$ python -c '
import sys
for p in "'"$PATH"'".split(":"):
    print(p)
'
/usr/sbin
/usr/bin
/sbin
/bin
...

已接受答案(和其他答案)的批评

这不是很可读:

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

可读性不太好,而且在出现错误时也很难调试:

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

也许更具可读性,但仍然很丑陋:

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

如果你的 python 中有 " 你会遇到麻烦:

$ python -c "导入系统
> for r in range(10): print 'rob'"

不要滥用 map 或列表推导式来获取 for 循环:

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

这些都是悲伤和糟糕的。不要做它们。

Any idea how this can be fixed?

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:

stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
             import_stmt | global_stmt | nonlocal_stmt | assert_stmt)

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, -:

$ python - <<-"EOF"
        import sys                    # 1 tab indent
        for r in range(10):           # 1 tab indent
            print('rob')              # 1 tab indent and 4 spaces
EOF

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

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

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:

$ python -c "
> import sys
> for p in '$PATH'.split(':'):
>     print(p)
> "
/usr/sbin
/usr/bin
/sbin
/bin
...

To avoid shell expansion use single-quotes:

$ python -c '
> import sys
> for p in "$PATH".split(":"):
>     print(p)
> '
$PATH

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:

$ python -c '
import sys
for p in "'"$PATH"'".split(":"):
    print(p)
'
/usr/sbin
/usr/bin
/sbin
/bin
...

Critique of the accepted answer (and others)

This is not very readable:

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

Not very readable, and additionally difficult to debug in the case of an error:

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

Perhaps a bit more readable, but still quite ugly:

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

You'll have a bad time if you have "'s in your python:

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

Don't abuse map or list comprehensions to get for-loops:

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

These are all sad and bad. Don't do them.

夕色琉璃 2024-08-25 00:25:05

只需使用 Return 并在下一行输入:

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

rob
rob
...

Just use Return and type it on the next line:

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

rob
rob
...
咆哮 2024-08-25 00:25:05
python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

工作正常。

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

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

works fine.

Use "[ ]" to inline your for loop.

故事灯 2024-08-25 00:25:05

此变体最适合在 Windows 和类 Unix 系统、Python 2 和 Python 3 上的命令行上放置多行脚本,无需管道:(

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

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

)在 Windows 上是:

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

Neat 在类 Unix 系统上的 Bash 上是:

python -c 

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

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 sys \nfor r in range(10): print("rob")'

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


用法:


输入是:


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:

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

(None of the other examples seen here so far did so.)

Neat on Windows is:

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

Neat on Bash on Unix-like systems is:

python -c 

This function turns any multiline-script into a portable command-one-liner:

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

Usage:

>>> 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\"\"\"')"

The input was:

print 'AA    A'
try:
 for i in 1, 2, 3:
  print i / 0
except:
 print """longer
message"""
import sys \nfor r in range(10): print("rob")'

This function turns any multiline-script into a portable command-one-liner:


Usage:


The input was:



    
差↓一点笑了 2024-08-25 00:25:05

问题不在于 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 that import 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.

迷爱 2024-08-25 00:25:05

如果您的系统兼容 POSIX.2,它应该提供 printf 实用程序:

printf "print 'zap'\nfor r in range(3): print 'rob'" | python

zap
rob
rob
rob

If your system is POSIX.2-compliant it should supply the printf utility:

printf "print 'zap'\nfor r in range(3): print 'rob'" | python

zap
rob
rob
rob
醉南桥 2024-08-25 00:25:05

我并不是一个真正的 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() 来执行命令,它会在分配后立即执行;然而,后来的检查显示 aNone

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

输出:

abc
[None]

对于方括号的情况,这并没有留下太多信息可供查找 - 但我偶然发现了这个页面我认为解释:

Python 提示和技巧 –第一版 - Python 教程 |梦想代码

如果您还记得,单行生成器的标准格式是一种括号内的单行“for”循环。这将生成一个“一次性”可迭代对象,该对象只能在一个方向上迭代,并且一旦到达末尾就无法重复使用。

“列表理解”看起来几乎与常规单行生成器相同,只是常规括号 - ( ) - 被方括号 - [ ] 替换。 alist 理解的主要优点是生成一个“列表”,而不是“一次性”可迭代对象,以便您可以来回浏览它、添加元素、排序等。

事实上,它是一个列表 -它只是它的第一个元素在执行后立即变为空:

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

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 of print (the difference being, sys.stdout.write takes arguments as a function, in parentheses - whereas print doesn't), then for a one-liner, you can get away with inverting the order of the command and the for, removing the semicolon, and enclosing the command in square brackets, i.e.:

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

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:

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

Output:

<generator object <genexpr> at 0xb771461c>

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):

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

Output:

abc
<generator object <genexpr> at 0xb777b734>

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 that a is None:

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

Output:

abc
[None]

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:

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.

And indeed it is a list - it's just its first element becomes none as soon as it is executed:

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

Output:

abc
<type 'list'>

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

Output:

abc
None

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:

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"

Output:

abc
01[None]
[None, None]

Notice that the second "list" b now has two elements, since its for loop explicitly ran twice; however, the result of sys.stdout.write() in both cases was (apparently) None.

等风也等你 2024-08-25 00:25:05

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

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 适用于 Python 3。

single/double quotes and backslash everywhere:

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

Much better:

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

Note: On some systems executable python is for Python 2 and may not be available. And executable python3 is for Python 3.

掀纱窥君容 2024-08-25 00:25:05

使用带有三引号的 python -c :

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

Use python -c with triple quotes:

python -c """
import os
os.system('pwd')
os.system('ls -l')
print('Hello, World!')
for _ in range(5):
    print(_)
"""
梨涡少年 2024-08-25 00:25:05

我想要一个具有以下属性的解决方案:

  1. 可读
  2. 读取标准输入进行处理其他工具的输出

其他答案中没有提供这两个要求,因此以下是如何在命令行上执行所有操作时读取标准输入:

grep special_string -r | sort | python3 <(cat <<EOF
import sys
for line in sys.stdin:
    tokens = line.split()
    if len(tokens) == 4:
        print("%-45s %7.3f    %s    %s" % (tokens[0], float(tokens[1]), tokens[2], tokens[3]))
EOF
)

I wanted a solution with the following properties:

  1. Readable
  2. Read standard input for processing output of other tools

Both requirements were not provided in the other answers, so here's how to read standard input while doing everything on the command line:

grep special_string -r | sort | python3 <(cat <<EOF
import sys
for line in sys.stdin:
    tokens = line.split()
    if len(tokens) == 4:
        print("%-45s %7.3f    %s    %s" % (tokens[0], float(tokens[1]), tokens[2], tokens[3]))
EOF
)
简美 2024-08-25 00:25:05

当我需要这样做时,我使用:

python -c "$(echo -e "import sys\nsys.stdout.write('Hello, World!\\\n')")"

注意 sys.stdout.write 语句中换行符的三个反斜杠。

When I needed to do this, I used:

python -c "$(echo -e "import sys\nsys.stdout.write('Hello, World!\\\n')")"

Note the triple backslash for the newline in the sys.stdout.write statement.

╭⌒浅淡时光〆 2024-08-25 00:25:05

如果您不想触摸标准输入并像您一样进行模拟通过“python cmdfile.py”,您可以从 Bash shell 执行以下操作:

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

如您所见,它允许您使用标准输入来读取输入数据。 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:

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

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.

嘿咻 2024-08-25 00:25:05

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

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

There is one more option. sys.stdout.write returns None, which keeps the list empty:

cat somefile.log|python -c "import sys;[line for line in sys.stdin if sys.stdout.write(line*2)]"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文