简体   繁体   English

Powershell 根据文本中的字符串重命名文本文件 --> 更简洁的脚本方式?

[英]Powershell rename text files based on strings in text --> More concise way for script?

I am trying to rename bankstatements in MT940-format using the account number and the statement date.我正在尝试使用帐号和对账单日期重命名 MT940 格式的银行对账单。

The statements contain the following (example):这些语句包含以下内容(示例):

    :20:
    :25:MHCBNL2AXXX/**0364525123**
    :28C:27/
    :60F:C200207EUR100000,00
    :61:2012311231D0000,1NMSCTOPF1234567890SDD TOPF1234567890
    :86:FR1234567890ARVAL FRANCE
    :62F:C**200207**EUR100000,00

I have written the following powershell script by combining some examples but it seems quite long for the purpose.我结合一些示例编写了以下 powershell 脚本,但就目的而言似乎很长。 Question: Is there a concise way to write this script?问:这个脚本有没有简洁的写法?

 $files = Get-ChildItem "C:\Dropbox\Temp\Gerard\test\*" -Include *.txt, *.ged
 for ($i=0; $i -lt $files.Count; $i++) 
 { 
   $filename = $files[$i].FullName        
  
  #Rename the file based on strings in the file
   $Account =  (Get-Content -Raw -Path $fileName) 
   $Account -match ":25:.+(\d{10})" 
   $Account = $matches[1]

   $StatementDate  =  (Get-Content -Raw -Path $fileName) 
   $StatementDate -match ":62F:C(?<content>.*)EUR"
   $StatementDate  = $matches['content']

   $file=Get-Item $filename
   $file.Basename 
   $extension=$file.Extension
   
   Rename-Item -Path $filename -NewName "$StatementDate-$Account$extension"
}

You could have achieved similar with the below:您可以通过以下方式实现类似的目标:

$Files = Get-ChildItem '/Users/acc/Downloads/bank/*' -Include '*.txt', '*.ged'
foreach ($File in $Files) {
    $Content = Get-Content -Path $File -Raw

    $Account = [Regex]::Match($Content, ':25:.+\*{2}(?<Account>\d{10})\*{2}').Groups['Account'].Value
    $StatementDate = [Regex]::Match($Content, ':62F:C\*{2}(?<StatementDate>\d+)\*{2}EUR').Groups['StatementDate'].Value

    Rename-Item -Path $File -NewName ('{0}-{1}{2}' -f $StatementDate, $Account, $File.Extension)
}
  • By using the foreach loop to iterate over objects in a collection, instead of a for (in-range) loop, you gain some aesthetic benefits like being able to easily access object's properties cleanly in the collection.通过使用foreach循环而不是for (范围内)循环来迭代集合中的对象,您可以获得一些美学上的好处,例如能够轻松地干净地访问集合中对象的属性。
    • For example, instead of getting an object instance of your file by calling Get-Item $filename to only get its extension, it is simplified by using the foreach loop and the current iterable is still an object of System.IO.FileSystemInfo.FileInfo .例如,不是通过调用Get-Item $filename来获取文件的 object 实例以仅获取其扩展名,而是通过使用foreach循环对其进行了简化,并且当前可迭代对象仍然是 object 的System.IO.FileSystemInfo.FileInfo Therefore we can get its extension by accessing the current iterable $File.extension .因此,我们可以通过访问当前可迭代的$File.extension来获取它的扩展名。
  • You were reading from a file multiple times with Get-Content where you only needed to do this once for each file.您使用Get-Content多次读取一个文件,而您只需要为每个文件执行一次。
  • In my opinion, using the .NET Match() method of the Regex class is cleaner than using the -match operator, but this is personal preference.在我看来,使用正则表达式 class 的 .NET Match()方法比使用-match运算符更干净,但这是个人偏好。
    • I did try to use the Matches() method so I could pass both regex patterns (split on a pipe | ) in one call, but for some reason, in both groups returned, not both patterns were matched;我确实尝试使用Matches()方法,因此我可以在一次调用中传递两个正则表达式模式(在 pipe |上拆分),但由于某种原因,在返回的两个组中,并非两个模式都匹配; one group contained a match for 'Account' whereas it did not for 'StatementDate', and vice versa on the other group.一组包含“Account”的匹配项,而它没有“StatementDate”的匹配项,反之亦然。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM