Harness the full power of Python in your shell scripts and on the command line.
pyl is a command line tool that let's you write terse but readable shell one-liners
using Python. It does this by introducing a few powerful syntax extensions, described
below.
Python has a super extensive standard library, making it the ultimate shell-scripting toolbox. The problem is that, while very concise compared to other languages, running Python snippets from within shell scripts is quite clunky. Consider the following code that base64-encodes each line of input:
$ ls | python -c $'import base64, sys\nfor l in sys.stdin: print(base64.b64encode(l.encode()).decode())'
TElDRU5TRQo=
UkVBRE1FLnJzdAo=
cHlwcm9qZWN0LnRvbWwK
c3JjCg==The biggest problem with inline Python is whitespace: Python requires newlines and indentation, and it's not convenient to include those in strings on the command line.
With pyl, the above command becomes:
$ ls | pyl 'for l in sys::stdin: { base64::b64encode(l.encode()).decode() }'
TElDRU5TRQo=
UkVBRE1FLnJzdAo=
cHlwcm9qZWN0LnRvbWwK
c3JjCg==pyl introduces a number of syntax extensions that, together, make it easy to write
readable shell one-lines that take full advantage of everything Python has to offer:
- Braces
Curly braces that appear immediately after a colon become indentation.
Example:
for i in range(3): { for j in range(4): { print(i * j); } }
is equivalent to
for i in range(3): for j in range(4): print(i * j)
- Line splitting at
; Lines are split at semicolons.
In normal Python, statements like
ifandforneed to appear on their own line. withpylyou can just use a semicolon:Example:
import sys; for arg in sys.argv: { print(arg); }
is equivalent to
import sys for arg in sys.argv: print(arg)
- Implicit
print If a block (either top-level or indented) ends without a semicolon, the last line is automatically printed (unless the block ends in another block).
In fact, the whole line is passed as-is to
print, so you can pass keyword arguments likesep.Example:
for i in range(10): { i, end='.' }
is equivalent to
for i in range(10): print(i, end='.')
- Inline-import
The
::operator can be used to access members of modules without explicitly importing them.Example:
urllib.parse::quote('hello world')
is equivalent to
print(__import__('urllib.parse').parse.quote('hello world'))
- Environment variables
Environment variables can be accessed with
$NAME.Example:
$HOMEis equivalent to
print(__import__('os').environ['HOME'])
- Command line arguments
Command line arguments can be accessed with
$INDEXwhereINDEXis a number.Example:
$1is equivalent to
print(__import__('sys').argv[1])