Powershell:将单个文件拆分为多个文件 - 使用字符串匹配条件
Powershell: Split a single file into multiple files - using string match criteria
我有一个包含 1GB 数据的文件。该数据实际上是数以千计的单个迷你文件的十分之一。
我需要提取每个单独的文件并将它们放在自己单独的 Distinct 文件中。
所以基本上,我需要从一个文件到 30K+ 个单独的文件。
这是我的文件的示例。
FILENAM1 VER 1 32 D
10/15/87 09/29/87
PREPARED BY ?????
REVISED BY ?????
DESCRIPTION USER DOMAIN
RECORD FILENAM1 VER 1 D SUFFIX -4541
100 05 ST-CTY-CDE-FMHA-4541 DISPLAY
200 10 ST-CDE-FMHA-4541 9(2) DISPLAY
300 10 CTY-CDE-FMHA-4541 9(3) DISPLAY
400 05 NME-CTY-4541 X(20) DISPLAY
500 05 LST-UPDTE-DTE-4541 9(06) DISPLAY
600 05 FILLER X DISPLAY 1REPORT NO. 08
DATA DICTIONARY REPORTER REL 17.0 09/23/21
PAGE 2 DREPORT 008
RECORD REPORT
-************************************************************************************************************************************
RECORD RECORD ---- D A T E ----
RECORD NAME LENGTH BUILDER TYPE
OCCURRENCES UPDATED CREATED
************************************************************************************************************************************ 0
FILENAM2 VER 1 176 D
03/09/98 02/21/84
PREPARED BY ??????
REVISED BY ??????
DEFINITION
我需要根据 VER 在位置 68、69 和 70 的匹配将文件拆分出来。我还需要为每个文件命名。该信息存储在同一行的 2-9 位置。在上面的示例中,该字符串是“FILENAM1”和 FILENAM2。
因此,仅使用上面的示例,我将创建两个输出文件,它们将被命名为 FILENAM1.txt 和 FILENAM2.txt。
由于我有 30K+ 个文件需要拆分,因此手动执行此操作是不可能的。
我有一个脚本可以将一个文件拆分成多个文件,但它不会按位置搜索字符串。
有人能帮我解决这个问题吗?
这是不起作用的脚本。希望我可以屠杀它并得到一些有效的结果....
$InputFile = "C:\COPIES.txt"
$Reader = New-Object System.IO.StreamReader($InputFile)
$OPName = @()
While (($Line = $Reader.ReadLine()) -ne $null) {
If ($Line -match "VER"(67,3)) {
$OPName = $Line.(2,8)
$FileName = $OPName[1].Trim()
Write-Host "Found ... $FileName" -foregroundcolor green
$OutputFile = "$FileName.txt"
}
Add-Content $OutputFile $Line
}
提前谢谢你,
-罗恩
我建议使用 switch
statement, which offers both convenient and fast line-by-line reading of files via -File
and regex-匹配通过 -Regex
:
$streamWriter = $null
switch -CaseSensitive -Regex -File "C:\COPIES.txt" {
'^.(.{8}).{58}VER' { # Start of a new embedded file.
if ($streamWriter) { $streamWriter.Close() } # Close previous output file.
# Create a new output file.
$fileName = $Matches[1].Trim() + '.txt'
$streamWriter = [System.IO.StreamWriter] (Join-Path $PWD.ProviderPath $fileName)
$streamWriter.WriteLine($_)
}
default { # Write subsequent lines to the same file.
if ($streamWriter) { $streamWriter.WriteLine($_) }
}
}
$streamWriter.Close()
注意:使用 [string]
类型的 .Substring()
方法的解决方案也是可能的,但会更冗长。
正则表达式的 ^.(.{8}).{58}
部分匹配每行的前 67 个字符,同时通过捕获组捕获(基于 1 的)第 2 列到第 9 列(文件名)中的字符(.{8})
,这使得捕获的文本在 automatic $Matches
variable 的索引 [1]
中可用。然后正则表达式的 VER
部分确保只有在第 68 列位置找到 VER
时该行才匹配。
为了高效output-file创建,使用了[System.IO.StreamWriter]
个实例,这比line-by-lineAdd-Content
调用快得多。此外,对于 Add-Content
,您必须确保目标文件不存在,因为现有内容将被附加到。
我有一个包含 1GB 数据的文件。该数据实际上是数以千计的单个迷你文件的十分之一。 我需要提取每个单独的文件并将它们放在自己单独的 Distinct 文件中。 所以基本上,我需要从一个文件到 30K+ 个单独的文件。
这是我的文件的示例。
FILENAM1 VER 1 32 D
10/15/87 09/29/87
PREPARED BY ?????
REVISED BY ?????
DESCRIPTION USER DOMAIN
RECORD FILENAM1 VER 1 D SUFFIX -4541
100 05 ST-CTY-CDE-FMHA-4541 DISPLAY
200 10 ST-CDE-FMHA-4541 9(2) DISPLAY
300 10 CTY-CDE-FMHA-4541 9(3) DISPLAY
400 05 NME-CTY-4541 X(20) DISPLAY
500 05 LST-UPDTE-DTE-4541 9(06) DISPLAY
600 05 FILLER X DISPLAY 1REPORT NO. 08
DATA DICTIONARY REPORTER REL 17.0 09/23/21
PAGE 2 DREPORT 008
RECORD REPORT-************************************************************************************************************************************ RECORD RECORD ---- D A T E ----
RECORD NAME LENGTH BUILDER TYPE OCCURRENCES UPDATED CREATED
************************************************************************************************************************************ 0
FILENAM2 VER 1 176 D
03/09/98 02/21/84
PREPARED BY ??????
REVISED BY ??????
DEFINITION
我需要根据 VER 在位置 68、69 和 70 的匹配将文件拆分出来。我还需要为每个文件命名。该信息存储在同一行的 2-9 位置。在上面的示例中,该字符串是“FILENAM1”和 FILENAM2。
因此,仅使用上面的示例,我将创建两个输出文件,它们将被命名为 FILENAM1.txt 和 FILENAM2.txt。
由于我有 30K+ 个文件需要拆分,因此手动执行此操作是不可能的。
我有一个脚本可以将一个文件拆分成多个文件,但它不会按位置搜索字符串。
有人能帮我解决这个问题吗?
这是不起作用的脚本。希望我可以屠杀它并得到一些有效的结果....
$InputFile = "C:\COPIES.txt"
$Reader = New-Object System.IO.StreamReader($InputFile)
$OPName = @()
While (($Line = $Reader.ReadLine()) -ne $null) {
If ($Line -match "VER"(67,3)) {
$OPName = $Line.(2,8)
$FileName = $OPName[1].Trim()
Write-Host "Found ... $FileName" -foregroundcolor green
$OutputFile = "$FileName.txt"
}
Add-Content $OutputFile $Line
}
提前谢谢你,
-罗恩
我建议使用 switch
statement, which offers both convenient and fast line-by-line reading of files via -File
and regex-匹配通过 -Regex
:
$streamWriter = $null
switch -CaseSensitive -Regex -File "C:\COPIES.txt" {
'^.(.{8}).{58}VER' { # Start of a new embedded file.
if ($streamWriter) { $streamWriter.Close() } # Close previous output file.
# Create a new output file.
$fileName = $Matches[1].Trim() + '.txt'
$streamWriter = [System.IO.StreamWriter] (Join-Path $PWD.ProviderPath $fileName)
$streamWriter.WriteLine($_)
}
default { # Write subsequent lines to the same file.
if ($streamWriter) { $streamWriter.WriteLine($_) }
}
}
$streamWriter.Close()
注意:使用 [string]
类型的 .Substring()
方法的解决方案也是可能的,但会更冗长。
正则表达式的
^.(.{8}).{58}
部分匹配每行的前 67 个字符,同时通过捕获组捕获(基于 1 的)第 2 列到第 9 列(文件名)中的字符(.{8})
,这使得捕获的文本在 automatic$Matches
variable 的索引[1]
中可用。然后正则表达式的VER
部分确保只有在第 68 列位置找到VER
时该行才匹配。为了高效output-file创建,使用了
[System.IO.StreamWriter]
个实例,这比line-by-lineAdd-Content
调用快得多。此外,对于Add-Content
,您必须确保目标文件不存在,因为现有内容将被附加到。