把Python写成shell脚本

为什么 Shell 脚本要用 Python 来写!? UNIX用户痛骂这是大逆不道.

比起 BAT/Bash 我更喜欢 Python 的语法, 高效又简洁, 想想看一个list bash要怎么写. 有 os/sys 模块的存在完全可以把 Python 写成类shell脚本(本质即调用shell命令), 再加上 pandas 等包更是让 Python 实用到一个新的高度(Windows干活干的多).

当然, 工具就是顺手就好. 你喜欢用什么写就用什么写.

不考虑更底层的应用. 别扯什么嵌入式驱动, C语言顶着你的脑门问: 师傅, 我是干什么的.

预备知识

其实就是当个 python 的 tldr

字符串处理

1
2
3
4
5
6
7
8
9
10
# 去除多余的空格
s = ' AAA '
s.strip() # lstrip().rstrip()
# 默认参数是空格, 其实可以上参数
s.strip('A')

# 大小写转换
s.upper() # s.lower()
# 大小写互换
s.swapcase()
1
2
3
4
5
6
7
8
9
# 分割字符串成为一个列表
# oj 题的读入
a, b, c = input().split()
# 按逗号分割
s = 'a,b,c'
ls = s.split(',')
# 反向合成 s
# 注意 p.join 是以 p 为分隔符, 把 ls 这样一个字符串列表拼接起来
new_s = ','.join(ls)
1
2
3
4
# 字符串反转
# 没有 reverse(), 但可以用切片 :)
s = 'abc'
reverse_s = s[::-1]
1
2
3
4
5
6
7
# 查找子串
s = 'Hello World!'
if 'hello' in s.lower():
# 找不到返回 -1
print(s.lower().find('hello')) # rfind
# 替换字串, 还可以指定替换次数
new_s = s.replace('hello', 'goodbye', 1)

字符串的语法糖

1
2
3
# 转义 这里的 \ 都不起作用了
s = r'C:\tmp\Game'
s = 'C:\\tmp\\Game'

用正则表达式!

文件I/O

实际案例

格式化文档

故事是这样的: 英语老师发了一个Word文档, 但纯文本非常的丑陋...文本拖进 vscode, markdownlint 爆了 1000+ 的 warnings...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import sys

filename = sys.argv[1]

with open(filename, 'r', encoding='utf-8') as f:
lines = f.readlines()

new_lines = []
count = 0
for i, line in enumerate(lines):
if line or (i > 0 and lines[i-1]):
if '。' not in line:
new_lines.append('')
new_lines.append(line)
new_lines.append('')
count += 1
else:
new_lines.append(line)

lines = [line.rstrip() for line in new_lines]

count += len(new_lines) - len(lines)

while lines and not lines[-1]:
lines.pop()
count += 1

trimmed_lines = []
for i, line in enumerate(lines):
if line or (i > 0 and lines[i-1]):
trimmed_lines.append(line)
count += 1

with open(filename, 'w', encoding='utf-8') as f:
f.write('\n'.join(trimmed_lines))
f.write('\n')

print(f"Modified {count} lines in file {filename}.")

系统操作

批量处理文件名

故事是这样的: 看到文件夹下的图片都是 微信图片_20210611232301, EAQ1vesW4AEaIdk, v2-1db136aa02affc53f6f31c99f6977a86 这样的命名, 我直接要爆炸了.

百度之, 发现居然还有人为之专门开发了改名程序.

明明几行代码就可以解决战斗的说.

1
2
3
4
5
6
7
8
9
10
11
12
import os
import time

# 获取当前工作目录
cwd = os.getcwd()

# 获取当前目录中所有的 .jpg 文件
files = [f for f in os.listdir(cwd) if f.endswith('.jpg')]

# 将文件重命名为 p(i).jpg, 其中 i 是文件的创建时间
for i, f in enumerate(sorted(files, key=lambda x: os.path.getctime(x))):
os.rename(f, 'p({}).jpg'.format(i+1))

实际使用的时候可以改改代码. 例如多一个.png, .webp, .gif 的识别啥的.

拓展阅读

[1]. Google Shell Style Guide 里面解释了你什么时候不应该使用 shell, 该怎么写 shell.

[2]. Shell 工具和脚本 - The missing semester of your cs education 是一个很好的shell入门.