[原创]PowerShell处理文本文件

来源:互联网 发布:mac被dns劫持 编辑:程序博客网 时间:2024/05/16 02:42

今天, 我们讨论一个使用正则表达式的问题. 题目源于某论坛, 内容如下:

-----------------------需求-------------------------
原始文件:(编号,姓名,工资)
-------------------------------------------

00014367423811520328285王小勇-109.00
C0024367423811520214121刁晓用-7.25
00034367423811520214071喻大森409.00
10014367423811520212695吕二青234.18
10036227003818620017835王得丹679.49
D0046227003813550029454刘小波767.22
R0054367423811520212943徐小明559.32

希望得到:

1︱4367423811520328285︱王小勇 | 0
2︱4367423811520214121︱刁晓用︱0
3︱4367423811520214071︱喻大森︱409
4︱4367423811520212695︱吕二青︱234.18
5︱6227003818620017835︱王得丹︱679.49
6︱6227003813550029454︱刘小波︱767.22
7︱4367423811520212943︱徐小明︱559.32
合计                   | 2649.21
   
-----------------------------------------------
1) 加入序号
2)用 | 分割各项
3)去掉编号前4个字符
3) 工资项若为负数,变为 0
4)最后将工资为正的,统计相加
 
-----------------------分析-------------------------
 
这种题目显然使用正则表达式是最方便不过的. 首先将源文件保存为salary.txt.
我把这个文件保存在 C:/Documents and Settings/Administrator 目录下, 请大家注意, 尽量避免使用管理员权限.
 
我们要从原始数据中提取出3个信息: 编号, 姓名, 工资项.
它们都有各自固定的特点, 因此我使用下面的正则表达式分别匹配这三项:
^.{4}(?<id>/d+)
(?<name>[/p{IsCJKUnifiedIdeographs}]+)
(?<salary>[/d.]*)
 
匹配名称时候, 我指定了中文, 日文, 韩文的特定集合. /p{IsCJKUnifiedldeographs}. 我想这是整个正则表达式的关键部分.
(?<>re)中, 指定正则表达式分组, <>中间是分组的名称. re是正则表达式.
 
现在, 我给出最后的代码样子:
 
${C:salary.txt} | `
ForEach-Object { $total = 0; $id = 1 } `
{ [void] ($_ -match '^.{4}(?<id>/d+)(?<name>[/p{IsCJKUnifiedIdeographs}]+)(?<salary>[/d.]*)'); `
$ofs = '|'; `
"$($id;$id++;$matches.id;$matches.name;'{0:F2}' -f [float]$matches.salary)"; `
$total += $matches.salary } `
{ "合计`t`t|$total" }
第一行从C:当前工作目录读取文件salary.txt, 然后通过管道, 传递给ForEach-Object命令. 首先我初始化了两个变量$total和$id, 分别用于记录最终的汇总值和每条记录的id号.
接下来正则表达式从输入中将信息分别匹配出来. 这些匹配的分组被保存在$matches哈希表中.
设置输出分隔符为|
拼接输出的信息: id, 员工id, 姓名, 然后用-f运算符指定浮点数的格式.
并将每个salary加到$total中.
最后打印汇总信息.
这里我利用了一个小技巧, 因为题目要求负数等价于0, 因此正则表达式就没有考虑负数的情况. $matches.salary就是$null值. $null值可以在数学运算中转化为数值0, 因此方便了整个脚本的实现.
原创粉丝点击