本篇内容主要讲解“awk脚本如何移植到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
如果你需要能够遍历任意数量的文件同时保持行数的持续计数(类似 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
来构建迭代器,该迭代器将遍历所有行并保持一个持久计数。
如果你需要同时使用 FNR
和 NR
,这是一个更复杂的循环:
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
和行数这三个你全都需要,仍然会有一些问题。如果确实如此,则使用三元组(其中两个项目是数字)会导致混淆。命名参数可使该代码更易于阅读,因此最好使用 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 程序,则通常需要将其分解为字段。Python 有几种方法可以做到这一点。这将把行按任意数量的连续空格拆分,返回一个字符串列表:
line.split()
如果需要另一个字段分隔符,比如以 :
分隔行,则需要 rstrip
方法来删除最后一个换行符:
line.rstrip("\n").split(":")
完成以下操作后,列表 parts
将存有分解的字符串:
parts = line.rstrip("\n").split(":")
这种拆分非常适合用来处理参数,但是我们处于偏差一个的错误场景中。现在 parts[0]
将对应于 awk 的 $1
,parts[1]
将对应于 awk 的 $2
,依此类推。之所以偏差一个,是因为 awk 计数“字段”从 1 开始,而 Python 从 0 开始计数。在 awk 中,$0
是整个行 —— 等同于 line.rstrip("\n")
,而 awk 的 NF
(字段数)更容易以 len(parts)
的形式得到。
例如,让我们将这个单行代码“如何使用 awk 从文件中删除重复行”转换为 Python。
awk
中的原始代码是:
awk '!visited[$0]++' your_file > deduplicated_file
“真实的” Python 转换将是:
import collectionsimport 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)
Python 社区提倡编写 Python 化的代码,这意味着它要遵循公认的代码风格。更加 Python 化的方法将区分唯一性和输入/输出的关注点。此更改将使对代码进行单元测试更加容易:
def unique_generator(things): visited = set() for thing in things: if thing in visited: continue visited.add(things) yield thing import sys for line in unique_generator(open("your_file")): sys.stdout.write(line)
将所有逻辑置于输入/输出代码之外,可以更好地分离问题,并提高代码的可用性和可测试性。
到此,相信大家对“awk脚本如何移植到Python”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。