''If' statements and one line Python scripts from the command line

Why do I receive a syntax error for the following one-liner Python code?

python -c 'import re; if True: print "HELLO";'
  File "<string>", line 1
    import re; if True: print "HELLO";
                ^
SyntaxError: invalid syntax

The following code works just fine:

python -c 'if True: print "HELLO";'

How can I change my one line to execute my intended script on a single line from the command line?



Solution 1:[1]

One option to work around this limitation is to specify the command with the $'string' format using the newline escape sequence \n.

python -c $'import re\nif True: print "HELLO";'

Note: this is supported by shells, such as Bash and Z shell (zsh), but it is not valid POSIX Bourne shell (sh).

As mentioned by slaadvak, there are some other workarounds here: Executing Python multi-line statements in the one-line command-line

Solution 2:[2]

The problem isn't with the import statement specifically. It’s that you have anything before a control flow statement. This won't work, either:

dan@dan:~> python -c 'a = "1234" ; if True: print "hi"'
  File "<string>", line 1
    a = "1234" ; if True: print "hi"
                  ^
SyntaxError: invalid syntax

According to the Python reference (7. Compound statements), ';' can only be used to combine "simple statements" together. In this case you're combining the simple statement import re, with if True:. if True isn't a simple statement, because it’s introducing flow control, and is therefore a compound statement. At least that's how I interpret the documentation.

Here's the full text from the Python reference:

Compound statements consist of one or more ‘clauses.’ A clause consists of a header and a ‘suite.’ The clause headers of a particular compound statement are all at the same indentation level. Each clause header begins with a uniquely identifying keyword and ends with a colon. A suite is a group of statements controlled by a clause. A suite can be one or more semicolon-separated simple statements on the same line as the header, following the header’s colon, or it can be one or more indented statements on subsequent lines

compound_stmt ::=  if_stmt
                   | while_stmt
                   | for_stmt
                   | try_stmt
                   | with_stmt
                   | funcdef
                   | classdef
                   | decorated
suite         ::=  stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement     ::=  stmt_list NEWLINE | compound_stmt
stmt_list     ::=  simple_stmt (";" simple_stmt)* [";"]

Solution 3:[3]

Why do I receive a syntax error for the following one-liner Python code?

Python grammar might forbid small_stmt ';' compound_stmt. The -c argument is probably is interpreted as file_input:

fileinput: (NEWLINE | stmt)* ENDMARKER
stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: import_stmt <in this case>
compound_stmt: if_stmt <in this case>

Note: there is a newline at the end of simple_stmt. if_stmt is not small_stmt; it can't follow another small_stmt after ';'. A newline is necessary to introduce compound_stmt after small_stmt.

It is not an issue because Bash allows multiline arguments. Just don't close the opening single quote until you are done, e.g.:

python -c '
> import re
> if 1:
>   print(1)
> '

1

Note: >s are printed by the shell itself here. It is not entered by hand.

Solution 4:[4]

You can embed newlines directly in the argument.

python -c 'import re
> if True:
>   print "HELLO"
> '

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter Mortensen
Solution 2 Peter Mortensen
Solution 3 Peter Mortensen
Solution 4 Peter Mortensen