目前,我通过一堆不记得的AWK,sed,Bash和一小部分Perl对文本文件进行操作。
我见过提到python在这种情况下有好处的几个地方。如何使用Python替换Shell脚本,AWK,sed和朋友?
目前,我通过一堆不记得的AWK,sed,Bash和一小部分Perl对文本文件进行操作。
我见过提到python在这种情况下有好处的几个地方。如何使用Python替换Shell脚本,AWK,sed和朋友?
Answers:
任何外壳程序都有几套功能。
基本的Linux / Unix命令。所有这些都可以通过子流程库获得。对于执行所有外部命令,这并不总是最好的首选。还要查看shutil中的一些命令,这些命令是独立的Linux命令,但是您可以直接在Python脚本中实现。os库中还有另一批Linux命令。您可以在Python中更简单地完成这些操作。
还有-奖金! - 更快速。外壳程序中的每个单独的Linux命令(有一些例外)都会派生一个子进程。通过使用Python shutil
和os
模块,您无需派生子进程。
外壳环境功能。这包括设置命令环境的内容(当前目录和环境变量以及诸如此类)。您可以直接从Python轻松地对此进行管理。
Shell编程功能。这就是所有过程状态代码检查,各种逻辑命令(如果有,为……等),测试命令及其所有亲属。函数定义的东西。在Python中,这一切非常容易。这是摆脱bash并在Python中完成的巨大胜利之一。
互动功能。这包括命令历史记录和“不”记录。编写shell脚本不需要此。这仅用于人类交互,而不用于脚本编写。
Shell文件管理功能。这包括重定向和管道。这比较棘手。其中大部分可以通过子流程来完成。但是一些容易在shell中执行的操作在Python中是令人不快的。具体来说就是这样的东西(a | b; c ) | something >result
。这将并行运行两个进程(输出a
作为的输入b
),然后是第三个进程。该序列的输出与并行运行,something
并将输出收集到名为的文件中result
。用任何其他语言表达都是很复杂的。
特定程序(awk,sed,grep等)通常可以重写为Python模块。不要太过分。替换您需要的内容并发展您的“ grep”模块。不要以编写替换“ grep”的Python模块开始。
最好的事情是您可以分步执行此操作。
os.walk
。这是一个很大的胜利,因为您不会产生那么多的进程。find
我拥有的多个脚本的python版本比较丑陋,冗长且无法维护。许多东西应该是 shell脚本,而其他许多东西则不应。并非所有内容都只需是Python或BASH(或其他任何内容)之一。
(a | b; c ) | something >result
通过将shell管道轻松传递给subprocess
使用shell=True
当然是 :)
看一下这些库,这些库可以帮助您不再编写Shell脚本(Plumbum的座右铭)。
另外,如果你要替换的awk,sed的和grep的东西基于Python的话,我建议小学项目 -
“ Pyed Piper”或pyp是类似于awk或sed的linux命令行文本操作工具,但是它使用标准的python字符串和列表方法以及自定义功能,这些功能在激烈的生产环境中可以快速生成结果。
我刚刚发现了如何结合bash和ipython的最佳部分。到目前为止,对我来说,这比使用子流程等更舒服。您可以轻松地复制现有bash脚本的大部分内容,例如以python方式添加错误处理:)这是我的结果:
#!/usr/bin/env ipython3
# *** How to have the most comfort scripting experience of your life ***
# ######################################################################
#
# … by using ipython for scripting combined with subcommands from bash!
#
# 1. echo "#!/usr/bin/env ipython3" > scriptname.ipy # creates new ipy-file
#
# 2. chmod +x scriptname.ipy # make in executable
#
# 3. starting with line 2, write normal python or do some of
# the ! magic of ipython, so that you can use unix commands
# within python and even assign their output to a variable via
# var = !cmd1 | cmd2 | cmd3 # enjoy ;)
#
# 4. run via ./scriptname.ipy - if it fails with recognizing % and !
# but parses raw python fine, please check again for the .ipy suffix
# ugly example, please go and find more in the wild
files = !ls *.* | grep "y"
for file in files:
!echo $file | grep "p"
# sorry for this nonsense example ;)
filelines = ! cat myfile
$var
在shell命令中一样使用python变量吗?哇。这应该是公认的答案。
从2015年和Python 3.4发行版开始,现在可以通过以下网址获得相当完整的用户交互shell:http : //xon.sh/或https://github.com/scopatz/xonsh
该演示视频不显示正在使用的管道,但他们在默认的shell模式下支持。
Xonsh('conch')会非常努力地模仿bash,因此您已经获得了肌肉记忆的东西,例如
env | uniq | sort -r | grep PATH
要么
my-web-server 2>&1 | my-log-sorter
仍然可以正常工作。
该教程篇幅很长,似乎涵盖了人们通常希望在ash或bash提示符下看到的大量功能:
?
&的帮助和超级帮助??
*.xsh
也可以导入的命令和/或脚本${}
$()
过程$[]
,使用的Python评估@()
*
或”的正则表达式的文件名,以及带有反引号的正则表达式的文件名最初有sh,sed和awk(以及find,grep和...)。这很好。但是awk可能是一个奇怪的小野兽,如果您不经常使用它,将很难记住。然后,伟大的骆驼创造了Perl。Perl是系统管理员的梦想。就像在类固醇上编写外壳脚本一样。文本处理(包括正则表达式)只是该语言的一部分。然后它变得丑陋了。人们试图用Perl进行大型应用程序。现在,请不要误会我的意思,Perl可以是一个应用程序,但是如果您不太谨慎的话,它可能(可以!)看起来像一团糟。然后就是所有这些平面数据业务。这足以使程序员发疯。
输入Python,Ruby等。这些确实是非常好的通用语言。它们支持文本处理,并且做得很好(尽管在语言的基本核心中可能并不紧密地缠在一起)。但是它们也可以很好地扩展,并且到最后仍然具有漂亮的代码。他们还开发了相当庞大的社区,其中有大量的图书馆可以满足大多数需求。
现在,对Perl的许多负面影响只是一个见解,当然有些人可以编写非常简洁的Perl,但是由于许多人抱怨创建混淆代码太容易了,因此您知道其中有些道理。真正的问题就变成了,您是否打算将这种语言用于比简单的bash脚本替换更多的事情。如果没有,请学习更多Perl。另一方面,如果您想要一种语言,并且随着您想做更多的事情而发展,那么我建议使用Python或Ruby。
无论哪种方式,祝您好运!
添加到先前的答案:检查pexpect模块以处理交互式命令(adduser,passwd等)
我喜欢Python的原因之一是,它比POSIX工具具有更好的标准化。我必须仔细检查每一位是否与其他操作系统兼容。在Linux系统上编写的程序在OSX的BSD系统上可能无法正常工作。使用Python,我只需要检查目标系统是否具有足够现代的Python版本。
更好的是,使用标准Python编写的程序甚至可以在Windows上运行!
我将根据经验给出我的看法:
对于外壳:
对于python:
我通常会为大多数事情选择bash,但是当我必须跨Windows边界进行操作时,我只会使用python。
在研究此主题时,我发现了这个概念验证代码(通过http://jlebar.com/2010/2/1/Replacing_Bash.html上的注释),可以使您“使用Python编写类似Shell的管道简洁的语法,并在有意义的地方利用现有的系统工具”:
for line in sh("cat /tmp/junk2") | cut(d=',',f=1) | 'sort' | uniq:
sys.stdout.write(line)
您可以在ShellPy库中使用python代替bash 。
这是一个从Github下载Python用户的化身的示例:
import json
import os
import tempfile
# get the api answer with curl
answer = `curl https://api.github.com/users/python
# syntactic sugar for checking returncode of executed process for zero
if answer:
answer_json = json.loads(answer.stdout)
avatar_url = answer_json['avatar_url']
destination = os.path.join(tempfile.gettempdir(), 'python.png')
# execute curl once again, this time to get the image
result = `curl {avatar_url} > {destination}
if result:
# if there were no problems show the file
p`ls -l {destination}
else:
print('Failed to download avatar')
print('Avatar downloaded')
else:
print('Failed to access github api')
如您所见,重音符(`)符号内的所有表达式都在shell中执行。并且在Python代码中,您可以捕获此执行的结果并对其执行操作。例如:
log = `git log --pretty=oneline --grep='Create'
该行将首先git log --pretty=oneline --grep='Create'
在shell中执行,然后将结果分配给log变量。结果具有以下属性:
标准输出从运行进程的标准输出的全部文本
stderr来自执行过程的stderr的全文
返回码的执行的返回码
这是库的一般概述,可在此处找到带有示例的更详细描述。
如果您的文本文件操作通常是一次性的,可能是在shell提示符下完成的,那么您将无法从python得到更好的结果。
另一方面,如果通常您需要一遍又一遍地执行相同(或类似)的任务,并且必须编写脚本来执行此操作,那么python很棒-而且您可以轻松地创建自己的库(您可以也使用shell脚本,但这比较麻烦)。
一个非常简单的例子来让人感觉。
import popen2
stdout_text, stdin_text=popen2.popen2("your-shell-command-here")
for line in stdout_text:
if line.startswith("#"):
pass
else
jobID=int(line.split(",")[0].split()[1].lstrip("<").rstrip(">"))
# do something with jobID
还要检查sys和getopt模块,它们是您首先需要的。
我已经在PyPI上发布了一个软件包:ez。
使用pip install ez
安装它。
它在shell中打包了常用命令,很好的是我的lib使用与shell基本相同的语法。例如,cp(源,目标)可以处理文件和文件夹!(shutil.copy shutil.copytree的包装,它决定何时使用哪一个)。更妙的是,它可以像R一样支持向量化!
另一个示例:没有os.walk,使用fls(path,regex)递归查找文件并使用正则表达式进行过滤,并返回具有或不具有全路径的文件列表
最后一个例子:您可以将它们组合起来以编写非常简单的脚本:
files = fls('.','py$'); cp(files, myDir)
一定要检查一下!我花了数百个小时来编写/改进它!