python awk_如何将awk脚本移植到Python

本文探讨了何时从awk转移到Python进行脚本编写,并详细介绍了如何在Python中实现awk的功能,如逐行处理、文件遍历、字段拆分等。通过提供具体的代码示例,展示了如何编写Pythonic的文本处理代码,强调了Python在可维护性和测试性方面的优势。
摘要由CSDN通过智能技术生成

python awk

脚本是重复解决问题的有效方法,而awk是编写脚本的出色语言。 它特别擅长于简单的文本处理,并且可以带您完成配置文件的某些复杂重写或目录中文件名的重新格式化。

何时从awk移至Python

但是到了某个时候,awk的局限性开始显现出来。 它没有将文件分解为模块的实际概念,它没有质量错误报告,并且缺少了现在被认为是语言工作原理的其他内容。 当编程语言的这些丰富功能有助于维护关键脚本时,移植将是一个不错的选择。

我最喜欢的完美移植awk的现代编程语言是Python。

在仔细考虑了上下文并确定了要用Python替代的东西之后,该编写代码了。

标准awk到Python功能

要记住以下Python功能:


   
   
with open ( some_file_name ) as fpin:
    for line in fpin:
        pass # do something with line

此代码将逐行循环遍历文件并处理这些行。

如果要访问行号(相当于awk的NR ),则可以使用以下代码:


   
   
with open ( some_file_name ) as fpin:
    for nr , line in enumerate ( fpin ) :
        pass # do something with line

Python中多个文件的类似awk的行为

如果您需要能够遍历任意数量的文件同时保持行数的持久计数(例如awk的FNR ),则此循环可以做到这一点:


   
   
def awk_like_lines ( list_of_file_names ) :
    def _all_lines ( ) :
        for filename in list_of_file_names:
            with open ( filename ) as fpin:
                yield from fpin
    yield from enumerate ( _all_lines ( ) )

该语法使用Python的生成器yield from构建遍历所有行并保持持久计数的迭代器

如果您需要FNRNR等效,这是一个更复杂的循环:


   
   
def awk_like_lines ( list_of_file_names ) :
    def _all_lines ( ) :
        for filename in list_of_file_names:
            with open ( filename ) as fpin:
                yield from enumerate ( fpin )
    for nr , ( fnr , line ) in _all_lines:
        yield nr , fnr , line

具有FNR,NR和线路的更复杂的awk功能

问题是否仍然存在,是否需要全部三个: FNRNRline 。 如果确实如此,则使用三元组(其中两个项目是数字)会引起混乱。 命名参数可使该代码更易于阅读,因此最好使用dataclass


   
   
import dataclass

@ dataclass. dataclass ( frozen = True )
class AwkLikeLine:
    content: str
    fnr: int
    nr: int

def awk_like_lines ( list_of_file_names ) :
    def _all_lines ( ) :
        for filename in list_of_file_names:
            with open ( filename ) as fpin:
                yield from enumerate ( fpin )
    for nr , ( fnr , line ) in _all_lines:
        yield AwkLikeLine ( nr = nr , fnr = fnr , line = line )

您可能想知道,为什么不从这种方法开始呢? 从其他地方开始的原因是,这几乎总是太复杂了。 如果您的目标是使通用库更容易将awk移植到Python,请考虑这样做。 但是编写一个可以使您确切地了解特定情况所需的循环的方法通常更容易实现,也更容易理解(因而易于维护)。

了解awk字段

一旦拥有与一行相对应的字符串,如果要转换awk程序,则通常需要将其分解为field 。 Python有几种方法可以做到这一点。 这将返回一个字符串列表,将行分割为任意数量的连续空格:

 line. split ( ) 

如果需要另一个字段分隔符,则类似这样的行将用分隔; 需要rstrip方法来删除最后一个换行符:

 line. rstrip ( " \n " ) . split ( ":" ) 

完成以下操作后,列表部分将具有分解字符串:

 parts = line. rstrip ( " \n " ) . split ( ":" ) 

这种拆分非常适合选择如何处理参数,但是我们处于一个一站式的错误情形中。 现在, parts [0]将对应于awk的$ 1parts [1]将对应于awk的$ 2 ,依此类推。这是因为awk从1开始计数“字段”,而Python从0开始计数。在awk的$ 0中是整行-等效于line.rstrip(“ \ n”)   并且awk的NF (字段数)更容易作为len(parts)检索。

在Python中移植awk字段

例如,让我们将单行代码从“ 如何使用awk从文件中删除重复行 ”转换为Python。

awk中的原始文件是:

 awk '!visited[$0]++' your_file > deduplicated_file 

“真实的” Python转换将是:


   
   
import collections
import sys

visited = collections . defaultdict ( int )
for line in open ( "your_file" ) :
    did_visit = visited [ line ]
    visited [ line ] + = 1
    if not did_visit:
        sys . stdout . write ( line )

但是,Python比awk具有更多的数据结构。 相反计数的访问(我们不使用,除非知道我们是否看到了一个线),为什么参观线路没有记录?


   
   
import sys

visited = set ( )
for line in open ( "your_file" ) :
    if line in visited:
        continue
    visited. add ( line )
    sys . stdout . write ( line )

制作Pythonic AWK代码

Python社区提倡编写Pythonic代码,这意味着它遵循公认的代码风格。 更加Python化的方法将区分唯一性输入/输出的关注点。 此更改将使对代码进行单元测试更加容易:


   
   
def unique_generator ( things ) :
    visited = set ( )
    for thing in things:
        if thing in visited:
            continue
        visited. add ( thing )
        yield thing

import sys
   
for line in unique_generator ( open ( "your_file" ) ) :
    sys . stdout . write ( line )

将所有逻辑置于输入/输出代码之外,可以更好地分离问题,并提高代码的可用性和可测试性。

结论:Python可能是一个不错的选择

将awk脚本移植到Python时,通常是在考虑适当的Python语言代码样式时重新实现核心需求,而不是通过条件/操作对条件/操作进行笨拙的音译。 考虑原始上下文并产生高质量的Python解决方案。 虽然有时候使用awk的Bash单行代码可以完成这项工作,但Python编码是通往更易于维护的代码的途径。

另外,如果您正在编写awk脚本,我相信您也可以学习Python! 如果您有任何疑问,请告诉我。

翻译自: https://opensource.com/article/19/11/awk-to-python

python awk

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值