Powershell 根据文本中的字符串重命名文本文件 --> 更简洁的脚本方式?
Powershell rename text files based on strings in text --> More concise way for script?
我正在尝试使用帐号和对账单日期重命名 MT940 格式的银行对账单。
语句包含以下(示例):
:20:
:25:MHCBNL2AXXX/**0364525123**
:28C:27/
:60F:C200207EUR100000,00
:61:2012311231D0000,1NMSCTOPF1234567890SDD TOPF1234567890
:86:FR1234567890ARVAL FRANCE
:62F:C**200207**EUR100000,00
我结合一些例子写了下面的powershell脚本,但是看起来有点长。
问题:这个脚本有没有简洁的写法?
$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"
}
您可以通过以下方式获得类似的效果:
$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)
}
- 通过使用
foreach
循环来迭代集合中的对象,而不是 for
(in-range) 循环,您可以获得一些美学上的好处,比如能够轻松访问对象的属性干净地放在集合中。
- 例如,不是通过调用
Get-Item $filename
来获取文件的对象实例来仅获取其扩展名,而是通过使用 foreach
循环来简化它,并且当前可迭代对象仍然是一个对象System.IO.FileSystemInfo.FileInfo
个。因此我们可以通过访问当前的可迭代对象 $File.extension
. 来获取它的扩展名
- 您使用
Get-Content
多次读取一个文件,而您只需要为每个文件执行一次。
- 在我看来,使用 .NET
Match()
method of the Regex class 比使用 -match
运算符更干净,但这是个人喜好。
- 我确实尝试使用
Matches()
方法,因此我可以在一次调用中传递两个正则表达式模式(在管道 |
上拆分),但由于某种原因,在两个组中返回,而不是两种模式都匹配;一组包含 'Account' 的匹配项,而 'StatementDate' 没有匹配项,另一组则相反。
我正在尝试使用帐号和对账单日期重命名 MT940 格式的银行对账单。
语句包含以下(示例):
:20:
:25:MHCBNL2AXXX/**0364525123**
:28C:27/
:60F:C200207EUR100000,00
:61:2012311231D0000,1NMSCTOPF1234567890SDD TOPF1234567890
:86:FR1234567890ARVAL FRANCE
:62F:C**200207**EUR100000,00
我结合一些例子写了下面的powershell脚本,但是看起来有点长。 问题:这个脚本有没有简洁的写法?
$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"
}
您可以通过以下方式获得类似的效果:
$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)
}
- 通过使用
foreach
循环来迭代集合中的对象,而不是for
(in-range) 循环,您可以获得一些美学上的好处,比如能够轻松访问对象的属性干净地放在集合中。- 例如,不是通过调用
Get-Item $filename
来获取文件的对象实例来仅获取其扩展名,而是通过使用foreach
循环来简化它,并且当前可迭代对象仍然是一个对象System.IO.FileSystemInfo.FileInfo
个。因此我们可以通过访问当前的可迭代对象$File.extension
. 来获取它的扩展名
- 例如,不是通过调用
- 您使用
Get-Content
多次读取一个文件,而您只需要为每个文件执行一次。 - 在我看来,使用 .NET
Match()
method of the Regex class 比使用-match
运算符更干净,但这是个人喜好。- 我确实尝试使用
Matches()
方法,因此我可以在一次调用中传递两个正则表达式模式(在管道|
上拆分),但由于某种原因,在两个组中返回,而不是两种模式都匹配;一组包含 'Account' 的匹配项,而 'StatementDate' 没有匹配项,另一组则相反。
- 我确实尝试使用