如何在Python中实现常见的bash习惯用法?[关闭]


242

目前,我通过一堆不记得的AWK,sed,Bash和一小部分Perl对文本文件进行操作。

我见过提到python在这种情况下有好处的几个地方。如何使用Python替换Shell脚本,AWK,sed和朋友?


3
pythonpy是awk的良好竞争者,并使用python语法进行sed:github.com/Russell91/pythonpy
RussellStewart 2014年

4
您可以使用设计时考虑到思想的shellpy替换为python github.com/lamerman/shellpy的
Alexander Ponomarev

这是我的问题,我不明白为什么它是基于意见的。最佳答案列出了Shell所做的每项主要工作,并告诉您如何在python中进行操作。我认为这以一种非意见的方式回答了这个问题。
克里斯·杰斐逊

这个问题,它的关闭,是在元正在讨论在这里
埃里克一个

Answers:


144

任何外壳程序都有几套功能。

  • 基本的Linux / Unix命令。所有这些都可以通过子流程库获得。对于执行所有外部命令,这并不总是最好的首选。还要查看shutil中的一些命令,这些命令是独立的Linux命令,但是您可以直接在Python脚本中实现。os库中还有另一批Linux命令。您可以在Python中更简单地完成这些操作。

    还有-奖金! - 更快速。外壳程序中的每个单独的Linux命令(有一些例外)都会派生一个子进程。通过使用Python shutilos模块,您无需派生子进程。

  • 外壳环境功能。这包括设置命令环境的内容(当前目录和环境变量以及诸如此类)。您可以直接从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模块开始。

最好的事情是您可以分步执行此操作。

  1. 用Python替换AWK和PERL。别的一切。
  2. 看一下用Python替换GREP。这可能会稍微复杂一些,但是您的GREP版本可以根据您的处理需求进行定制。
  3. 看一下用来代替FIND的Python循环os.walk。这是一个很大的胜利,因为您不会产生那么多的进程。
  4. 看一下用Python脚本替换常见的shell逻辑(循环,决策等)。

6
写道:“交互功能。这包括命令历史记录和其他内容。您不需要它。” 恐怕没人能说出一个人真正需要什么。也许他会。此外,以Idle和IPython之间的区别为例,这些功能在交互式Shell中非常有意义。
heltonbiker 2011年

47
我衷心希望人们完全放弃shell脚本。我知道在* nix世界中,黑客实际上是一种宗教,但我真的很疲倦于试图解释操作系统中植入的所有黑客解决方法。每个人都决定推出自己的版本的那一天,微型工具(awk,sed,top,base等)的新颖性消失了。当我想到用一些精心设计的Python模块可以轻松替代的笨拙的小工具上浪费大量的工时时,我感到非常畏缩。:: sigh ::
Evan Plaice 2012年

40
我不同意@EvanPlaice,因为find我拥有的多个脚本的python版本比较丑陋,冗长且无法维护。许多东西应该是 shell脚本,而其他许多东西则不应。并非所有内容都只需是Python或BASH(或其他任何内容)之一。
mikebabcock 2012年

8
@mikebabcock理想情况下,会有一个完整的库来实现基本* nix堆栈提供的所有微型工具。诸如find()和last()之类的函数将被包含在内,而不是管道,而currying和lazy-loading的组合将能够将它们全部粘合在一起。拥有一个可以在所有发行版中以标准方式工作的POSIX脚本环境不是很好吗?像这样的东西还不存在……
Evan Plaice 2012年

2
(a | b; c ) | something >result通过将shell管道轻松传递给subprocess使用shell=True
iruvar的

103

当然是 :)

看一下这些库,这些库可以帮助您不再编写Shell脚本(Plumbum的座右铭)。

另外,如果你要替换的awk,sed的和grep的东西基于Python的话,我建议小学项目 -

“ Pyed Piper”或pyp是类似于awk或sed的linux命令行文本操作工具,但是它使用标准的python字符串和列表方法以及自定义功能,这些功能在激烈的生产环境中可以快速生成结果。


也可以看看Envoy,它是sh github.com/kennethreitz/envoy
AllanLRH 2015年

57

我刚刚发现了如何结合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 ;)

请参阅有关系统外壳程序命令的 IPython文档,并将其用作系统外壳程序


11
之所以提出反对,是因为出于某些奇怪的原因,在IPython中没有人提到过!-命令,这绝对是关键。特别是因为您还可以将其输出分配给变量(行列表),例如filelines = ! cat myfile
kampu

您可以像$var在shell命令中一样使用python变量吗?哇。这应该是公认的答案。
Chiel 10 Brinke

您也可以在Jupyter笔记本中使用它
Yuval Atzmon

44

从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模式
  • 使用捕获的子过程,使用的未捕获子$()过程$[],使用的Python评估@()
  • 带有“ *或”的正则表达式的文件名,以及带有反引号的正则表达式的文件名

但是,为什么所有这些答案似乎都只是在为那些不懂bash的人重新发明轮子呢?我已经对bash有了一定程度的适应,这些答案中的每一个似乎都将导致更多工作而无济于事。这些答案都是针对害怕(或不想花时间学习)bash的python的人,对吗?
Buttle Butkus

似乎有一些缺点,例如要求对.xsh带有xonsh代码的文件使用扩展名:github.com/xonsh/xonsh/issues/2478。否则,您必须使用evalx直接从.py文件中调用它。
安德里(Andry)

31
  • 如果要使用Python作为外壳,为什么不看看IPython?交互式学习语言也很好。
  • 如果您进行大量的文本操作,并且将Vim用作文本编辑器,则还可以直接在python中为Vim编写插件。只需在Vim中输入“:help python”,然后按照说明进行操作或查看此演示文稿即可。编写可直接在编辑器中使用的函数是如此简单和强大!

8
有一个名为“ sh”的ipython配置文件,使解释器非常像shell。
Autoplectic

3
ipython的“ sh”配置文件已删除了一段时间。
gdw2

>>>结果=!dmesg | grep -i'usb'#the!操作员做到了一切
Permafacture

16

最初有sh,sed和awk(以及find,grep和...)。这很好。但是awk可能是一个奇怪的小野兽,如果您不经常使用它,将很难记住。然后,伟大的骆驼创造了Perl。Perl是系统管理员的梦想。就像在类固醇上编写外壳脚本一样。文本处理(包括正则表达式)只是该语言的一部分。然后它变得丑陋了。人们试图用Perl进行大型应用程序。现在,请不要误会我的意思,Perl可以是一个应用程序,但是如果您不太谨慎的话,它可能(可以!)看起来像一团糟。然后就是所有这些平面数据业务。这足以使程序员发疯。

输入Python,Ruby等。这些确实是非常好的通用语言。它们支持文本处理,并且做得很好(尽管在语言的基本核心中可能并不紧密地缠在一起)。但是它们也可以很好地扩展,并且到最后仍然具有漂亮的代码。他们还开发了相当庞大的社区,其中有大量的图书馆可以满足大多数需求。

现在,对Perl的许多负面影响只是一个见解,当然有些人可以编写非常简洁的Perl,但是由于许多人抱怨创建混淆代码太容易了,因此您知道其中有些道理。真正的问题就变成了,您是否打算将这种语言用于比简单的bash脚本替换更多的事情。如果没有,请学习更多Perl。另一方面,如果您想要一种语言,并且随着您想做更多的事情而发展,那么我建议使用Python或Ruby。

无论哪种方式,祝您好运!




7

我喜欢Python的原因之一是,它比POSIX工具具有更好的标准化。我必须仔细检查每一位是否与其他操作系统兼容。在Linux系统上编写的程序在OSX的BSD系统上可能无法正常工作。使用Python,我只需要检查目标系统是否具有足够现代的Python版本。

更好的是,使用标准Python编写的程序甚至可以在Windows上运行!


1
“用标准Python编写的程序甚至可以在Windows上运行”:开玩笑吗?
让·弗朗索瓦·法布尔

6

我将根据经验给出我的看法:

对于外壳:

  • Shell可以很容易地产生只读代码。编写它,当您重新使用它时,将永远不会再想出自己做了什么。这很容易做到。
  • shell可以使用管道在一行中进行大量文本处理,拆分等操作。
  • 当集成不同编程语言中的程序调用时,它是最好的粘合语言。

对于python:

  • 如果要包括Windows的可移植性,请使用python。
  • 当您必须要操作的不仅仅是文本(例如数字集合)时,python可能会更好。为此,我建议使用python。

我通常会为大多数事情选择bash,但是当我必须跨Windows边界进行操作时,我只会使用python。



3

我建立了半长的shell脚本(300-500行)和Python代码,它们具有相似的功能。当执行许多外部命令时,我发现该外壳更易于使用。当有大量的文本操作时,Perl也是一个不错的选择。



2

最好的选择是专门针对您的问题的工具。如果正在处理文本文件,则Sed,Awk和Perl是最有竞争力的竞争者。Python是一种通用的动态语言。与任何通用语言一样,文件处理也受支持,但这并不是其核心目的。如果我特别需要动态语言,我会考虑使用Python或Ruby。

简而言之,请非常好地学习Sed和Awk,以及带有* nix风格的所有其他好东西(所有Bash内置,grep,tr等)。如果您对文本文件处理感兴趣,那么您已经在使用正确的东西。


2

您可以在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的全文

返回码的执行的返回码

这是库的一般概述,可在此处找到带有示例的更详细描述。


1

如果您的文本文件操作通常是一次性的,可能是在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模块,它们是您首先需要的。


1

我已经在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)

一定要检查一下!我花了数百个小时来编写/改进它!


1
看起来很有趣,但是我无法突破pypi.python.org/pypi/ez上未格式化的文档,对不起...
Greg Dubicki
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.