[原创]使用PowerShell来完成像awk一样对多个文件的筛选(一)

本文介绍了如何使用PowerShell来完成类似awk的文件筛选和合并任务,通过扩展PowerShell的功能,实现对多个文件的高效处理。文中展示了具体的代码示例,包括如何初始化HashTable、操作文件以及使用switch语句,最终简化了原本复杂的任务,提高了处理效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者: Edengundam(马涛)
本篇文章引用的小例子来自如下链接:
 
又是一篇重量级的精华帖, 主要讲解了awk在shell中的重要作用. 编写本篇例子, 费了我很长时间, 一开始我就使用awk的思路, 试图利用PowerShell完成. 写完后, 依然还是模仿awk的风格, 并且整个代码更加冗长, 我沉思半晌, 终于领悟到了一个关键性的问题. 正如, PowerShell团队leader所说: "Unix世界文件, 大都是字符串, 因此在Unix环境下, 针对文本的处理工具譬如: 'awk, sed, join, paste, uniq, sort 和column'等等都异常强大." 在Windows的环境中, 所有信息被抽象, 因此, PowerShell 的特性也就必须进行一定的扩展, 才能更好的适应文本操作. 下面对于每种问题, 我都会给出相应的代码, 这里用到了很多很多PowerShell中的知识, 如果想真正看懂, 需要把基本功大扎实. 基本功越好, 你就一定遇到更少的障碍.
 
1. 用某一文件的一个域替换另一个文件中的的特定域
 

PS C:/PowerShell/test1> gc passwd s2002408030068:x:527:527::/home/dz02/s2002408030068:/bin/pw s2002408032819:x:528:528::/home/dz02/s2002408032819:/bin/pw s2002408032823:x:529:529::/home/dz02/s2002408032823:/bin/pw

 

PS C:/PowerShell/test1> gc shadow

s2002408030068:$1$d8NwFclG$v4ZTacfR2nsbC8BnVd3dn1:12676:0:99999:7::: s2002408032819:$1$UAvNbHza$481Arvk1FmixCP6ZBDWHh0:12676:0:99999:7::: s2002408032823:$1$U2eJ3oO1$bG.eKO8Zupe0TnyFhWX9Y.:12676:0:99999:7:::

我们希望用shadow中第二个域中的字符串替换passwd中的第二个域的'x'. 代码示例如下:

PS C:/PowerShell/test1> gc shadow | %{ $hash = @{} } { $key,$value = $_.trim().split(':')[0,1]; $hash.$key = $value }

我们初始化了一个名称为hash的HashTable, 接下来用了一个perl的多值赋值语句将我们需要信息用数组slice技巧赋值, 最后添加到hash中. 貌似分割太复杂了, sigh...接下来,我们还要将这些数据与passwd中的信息进行合并.

PS C:/PowerShell/test1> switch -f passwd { { $_ -notmatch '^/s*$' } { $ofs = ":"; $input = $_.split(':'); $input[1] = $hash[$input[0]]; "$input" } } s2002408030068:$1$d8NwFclG$v4ZTacfR2nsbC8BnVd3dn1:527:527::/home/dz02/s2002408030068:/bin/pw s2002408032819:$1$UAvNbHza$481Arvk1FmixCP6ZBDWHh0:528:528::/home/dz02/s2002408032819:/bin/pw s2002408032823:$1$U2eJ3oO1$bG.eKO8Zupe0TnyFhWX9Y.:529:529::/home/dz02/s2002408032823:/bin/pw

完成任务, 不过我确实用了很多代码, 看起来很复杂. 这里我特意使用了强大的switch来操作文件, 分支条件也使用了表达式.

写到这里, 我觉得很郁闷, 如果我们能获得awk默认的特性, 设置一些默认的变量, 那么我就会更加简单了.

***********************************

我最终决定, 扩展自己的哦PowerShell, 完成一些令人crazy的事情. 让PowerShell具有awk的能力. 以下代码绝对原创:

***********************************

filter awk ([scriptblock] $cmd = $args[0], [regex] $delimiter='/s+')

{

$line = @();

$nf = 0;

$line = @($delimiter.split($_.Trim()));

$nf = $line.length;

$0 = $_;

for ($i = 1; $i -le $nf; $i++)

{

Invoke-Expression "`$$i = '$($line[$i - 1])'"

}

& $cmd

}

好了, 虽然他还不能算得上好使, 但是一般工作都可以完成了. 下面我们测试一下他. 目前他只能支持从管道读取数据.

2. 连接两个文件, 连接属性是某个域上的字串

我们先看下输入数据:

PS C:/PowerShell/test2> gc file1

0011AAA 200.00 20050321

0012BBB 300.00 20050621

0013DDD 400.00 20050622

0014FFF 500.00 20050401

PS C:/PowerShell/test2> gc file2

I0011 11111

I0012 22222

I0014 55555

I0013 66666

我们需要根据file1中第一个域上前4个字符和file2上第一个域的2到5个字符进行比较. 将file2第二个域的数据连接到file1上. 我们来测试下awk的功能吧:

PS C:/PowerShell/test2> $hash = @{}

PS C:/PowerShell/test2> gc file2 | awk -cmd {$hash[$1.substring(1,4)] = $2}

PS C:/PowerShell/test2> gc file1 | awk -cmd { "$0 $($hash[$1.substring(0,4)])" }

0011AAA 200.00 20050321 11111

0012BBB 300.00 20050621 22222

0013DDD 400.00 20050622 66666

0014FFF 500.00 20050401 55555

OK了, 是不是简单了很多呢??

在下一次中, 我将会继续完成3,4题. 希望, 今天的例子足以让你感受到PowerShell的强大. awk 大约花费了我30分钟的时间. 这种扩展带来了更加快速的处理效率.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值