Using bash echo command to input into a python one liner - python

I am trying to input a string using echo into a Python one liner then perform a Caeasar's Cipher on the string.
One of the examples my instructor gave me was this.
~ $ echo "Hello Holly." | python -c "import sys; [print(line) for line in sys.stdin]"
The output is suppose to be: Hello Holly.
How ever when I type the command in I get:
File "<string>", line 1
import sys; [print(line) for line in sys.stdin]
^
SyntaxError: invalid syntax
I would appreciate it if someone could point out the error to me. I am using Python 2.6 on Centos 6.
Thanks.

In Python 2 print is a statement, not a function. Try this instead:
echo "Hello Holly." | python -c "import sys; print [line for line in sys.stdin]"
Alternatively, you could use the following to just print plain text (thanks #mgilson):
echo "Hello Holly." | python -c "import sys; print ' '.join([line for line in sys.stdin])"

It looks like you are using python2 while your isntructor is using python 3.

Related

Passing a shell variable to inline python in a shell script

I have a simple shell script where i want to be able to pass variables to some inline python i will write. For example like this
funny=879
echo $funny
python -c "
print(f"hello {$funny}")
"
However this prints
879
File "<string>", line 2
print(fhello
^
SyntaxError: unexpected EOF while parsing
(pipeline) $
Any thoughts on what i could be doing wrong? I know i am setting the variable correct because when i do echo it prints out the variable so it is definitely set correct but for some reason python script is not able to use it.
It's because you're using outer double quotes.
python -c "print(f"hello {$funny}")"
Gets turned into:
python -c print(fhello {879})
So python is passed 2 separate strings.
The inner double quotes would need to be escaped in order to get passed through to python.
$ funny=879; python3 -c "print(f\"hello $funny\")"
hello 879
Instead of messing around with quoting - if you export your variables you can access them from python using the os.environ dict.
$ export funny=879; python -c 'import os; print(os.environ["funny"])'
879
You can use the var=value command syntax and omit the export (note the lack of a semicolon)
$ funny=879 fonny=978 python3 -c 'import os; print(os.environ["funny"], os.environ["fonny"])'
879 978

Multiline python code execution in terminal (Windows)

As the question states, I would like to know how to execute arbitrary python code in a windows terminal (or Anaconda Prompt). Please note that I am on Windows. In general, terminal execution is something like:
>>python -c "print('Some Text to Print')"
But what happens if I have multiple lines with indents and indent-indents. Here is an example of things I have tried (please note that I am forcing two lines here in some way, the solution "for i in range(10): print(i)" is not appropriate to the question since this only has one line of python code):
>>python -c "for i in range(10):; print(i)"
>>python -c "for i in range(10):\nprint(i)"
>>python -c "for i in range(10):\n print(i)"
>>python -c "for i in range(10):\n\tprint(i)"
Now clearly I can do this:
>>python -c "exec('for i in range(10):\n\tprint(i)')"
and this solution works. But this solution feels wrong. Is there a more pythonic way? In particular, why do the newline and tab characters work for "exec()" but not for "python -c"?
Have you already tried with ^ ?
In this case if you will not be careful with spaces, you will obtain an IndentationError: unexpected inden
python -c ^
More? "for i in range(2): ^
More? print(i)"
[EDIT]
There are also another way:
python -c ^
More? "for i in range(2):^ print(i)"
0
1
^ is the EOL character used as the new line character in most other non-Unix operating systems, including Microsoft Windows and Symbian OS.
You can do
> echo "for i in range(2):
>> print(i)
>> " | python
0
1

Python -c bash swtich newline

I'd like to run the command:
print "hello"
print "world!"
from python with the -c switch from bash, something like this:
python -c 'print "hello" \n print "world"'
But I can't figure out what the correct newline character should be in the string after the -c switch.
How about:
python -c 'print "hello"; print "world"'
some python statements cannot be written in one line, so I recommend this:
python -c '
print "hello"
print "world"
'
in this way statements such as for can be appeared.
python -c 'print "hello\nworld"'

python -c and `while`

Is there a way to loop in while if you start the script with python -c? This doesn't seem to be related to platform or python version...
Linux
[mpenning#Hotcoffee ~]$ python -c "import os;while (True): os.system('ls')"
File "<string>", line 1
import os;while (True): os.system('ls')
^
SyntaxError: invalid syntax
[mpenning#Hotcoffee ~]$
[mpenning#Hotcoffee ~]$ python -V
Python 2.6.6
[mpenning#Hotcoffee ~]$ uname -a
Linux Hotcoffee 2.6.32-5-amd64 #1 SMP Sun May 6 04:00:17 UTC 2012 x86_64 GNU/Linux
[mpenning#Hotcoffee ~]$
Windows
C:\Users\mike_pennington>python -c "import os;while True: os.system('dir')"
File "<string>", line 1
import os;while True: os.system('dir')
^
SyntaxError: invalid syntax
C:\Users\mike_pennington>python -V
Python 2.7.2
C:\Users\mike_pennington>
I have tried removing parenthesis in the while statement, but nothing seems to make this run.
python -c $'import subprocess\nwhile True: subprocess.call(["ls"])'
would work (note the $'...' and the \n).
But it could be that it only works under bash - I am not sure...
Multiline statements may not start after a statement-separating ; in Python – otherwise, there might be ambiguities about the code blocks. Simply use line breaks in stead of ;. This "works" on Linux:
$ python -c "import os
while True: os.system('ls')"
Not sure how to enter this on Windows, but why not simply write the commands to a .py file if it's more than one line?
Don't know about windows, if all you want is to be able to type in one-liners, you could consider line breaks inside quotes:
% python -c "import os;
while (True):
os.system('ls')"
If you really must do this in windows, you could use exec:
python -c "exec \"import os;\rwhile True:\r os.system('dir')\""
(I substituted dir so it works on my windows system)

Python one-liner to print every file in the current directory

How can I make the following one liner print every file through Python?
python -c "import sys;print '>>',sys.argv[1:]" | dir *.*
Specifically would like to know how to pipe into a python -c.
DOS or Cygwin responses accepted.
python -c "import os; print os.listdir('.')"
If you want to apply some formatting like you have in your question,
python -c "import os; print '\n'.join(['>>%s' % x for x in os.listdir('.')])"
If you want to use a pipe, use xargs:
ls | xargs python -c "import sys; print '>>', sys.argv[1:]"
or backticks:
python -c "import sys; print '>>', sys.argv[1:]" `ls`
You can read data piped into a Python script by reading sys.stdin. For example:
ls -al | python -c "import sys; print sys.stdin.readlines()"
It is not entirely clear what you want to do (maybe I am stupid). The confusion comes from your example which is piping data out of a python script.
If you want to print all files:
find . -type f
If you want to print only the current directory's files
find . -type f -maxdepth 1
If you want to include the ">>" before each line
find . -type f -maxdepth 1 | xargs -L 1 echo ">>"
If you don't want the space between ">>" and $path from echo
find . -type f -maxdepth 1 | xargs -L 1 printf ">>%s\n"
This is all using cygwin, of course.
ls | python -c "import sys; print sys.stdin.read()"
just read stdin as normal for pipes
would like to know how to pipe though
You had the pipe the wrong way round, if you wanted to feed the output of ‘dir’ into Python, ‘dir’ would have to be on the left. eg.:
dir "*.*" | python -c "import sys;[sys.stdout.write('>>%s\n' % line) for line in sys.stdin]"
(The hack with the list comprehension is because you aren't allowed a block-introducing ‘for’ statement on one line after a semicolon.)
Clearly the Python-native solution (‘os.listdir’) is much better in practice.
Specifically would like to know how to pipe into a python -c
see cobbal's answer
piping through a program is transparent from the program's point of view, all the program knows is that it's getting input from the standard input stream
Generally speaking, a shell command of the form
A | B
redirects the output of A to be the input of B
so if A spits "asdf" to standard output, then B gets "asdf" into its standard input
the standard input stream in python is sys.stdin

Categories

Resources