regex Powershell -将数据解析到新文件中-硬返回/换页问题

niknxzdl  于 2023-01-27  发布在  Shell
关注(0)|答案(1)|浏览(95)

我有一个包含以下信息的txt文件:
第1页
学生1数据
FF换页符(可能出现,也可能不出现)[INCLUDE in parsed file]
第2页
学生1数据
学生1数据

*成绩单结束

FF换页符(明确出现在此位置)[不包含在解析文件中]
第1页
学生2数据
学生2数据
FF换页符(可能出现,也可能不出现)[INCLUDE in parsed file]
第2页
学生2数据

*成绩单结束

FF换页符(明确出现在此位置)[不包含在解析文件中]
第1页
学生3数据
学生3数据
学生3数据
FF换页符(可能出现,也可能不出现)[INCLUDE in parsed file]

*成绩单结束

FF换页符(明确出现在此位置)[不包含在解析文件中]
我正在尝试解析出数据,这样我就可以得到三个单独的文件,并删除只出现在"记录结束"行之后的表单提要。
我最终得到三个文件:
包含"学生1数据"的日期_EDI_TRANSCRIPT_1.txt
包含"学生2数据"的日期_EDI_TRANSCRIPT_2.txt
包含"学生3数据"的日期_EDI_TRANSCRIPT_3.txt
但是,解压缩文件中的换页在每个文件的开头。我想从文件的开头和结尾删除它。
我得到这个:

我想得到这个:

我的代码是:

$data =  Get-Content "C:\EDICleanUp\1_ToBeProcessed\edi.txt" #Reading file
$Transcript = "_EDI_TRANSCRIPT_"
$Tdate = get-date -Format yyyy-MM-dd
$ProcessedFilePath = "C:\EDICleanUp\2_Processed"
$Complete = "C:\EDICleanUp\3_Original"
$ToBeProcessed = "C:\EDICleanUp\1_ToBeProcessed\edi.txt"

$fileIndex = 1; #To create file name

for ($itr = 0; $itr -le $data. Length; $itr++){    

    if($data[$itr] -eq "**********  END OF TRANSCRIPT  **********"){ 
       $fileIndex+=1;
continue;

}
if((Test-Path "$ProcessedFilePath$Tdate$Transcript$fileIndex.txt") -eq $false){
New-Item "$ProcessedFilePath$Tdate$Transcript$fileIndex.txt" -ItemType "File"
}
#Append text to the file
Add-Content "$ProcessedFilePath$Tdate$Transcript$fileIndex.txt" $data[$itr]
}
##Move original file to completed directory
Move-item $ToBeProcessed $Complete

我"认为"问题在于:

if($data[$itr] -eq "**********  END OF TRANSCRIPT  **********"){ 
    $fileIndex+=1;

我找不到合适的代码来查找硬返回/表单提要。
我尝试了以下变体:
'*******\s\s [脚本结束]********+\f'
但运气不好。
任何投入都将不胜感激。

hmae6n7t

hmae6n7t1#

我建议使用Get-Content-Raw一次读取整个文件,并使用基于regex-split operator将文件拆分为感兴趣的块,而不是逐行处理。
一个简单的例子:

# Read the file into a single, multi-line string.
$data =  Get-Content -Raw C:\EDICleanUp\1_ToBeProcessed\edi.txt
$Tdate = Get-Date -Format yyyy-MM-dd
$nr = @{ Value = 0 } # output file sequence number

$data `
  -split ([regex]::Escape('********** END OF TRANSCRIPT **********') + '\r?\n\f') `
  -ne '' |
  Set-Content -NoNewline -LiteralPath { 
    '{0}_EDI_TRANSCRIPT_{1}.txt' -f $Tdate, ++$nr.Value 
  }
  • [regex]::Escape('********** END OF TRANSCRIPT **********') + '\r?\n\f'是用于拆分文件内容的正则表达式:
  • [regex]::Escape('********** END OF TRANSCRIPT **********')转义搜索字符串的文字部分,以便在正则表达式中使用(实际上,此\-转义*字符,它们是正则表达式元字符。
  • \r?\n匹配Windows格式的CRLF换行符(\r\n)或Unix的LF换行符(\n
  • \f与FF字符匹配。
  • 注:从示例数据中无法确定FF字符是以换行符开头,还是以换行符结尾,或者根本没有换行符-请根据需要调整上述内容。此外,假设每个END OF TRANSCRIPT示例都由相同的固定数量的*字符和空格包围。
      • 如果在FF字符之前 * 没有 * 换行符,或者您认为换行符总是CRLF序列或只是一个LF字符**,您可以使用包含转义序列的可扩展字符串常量("...")(参见下一节),并通过-splitSimpleMatch选项进行*常量 * 拆分;例如:
$data -split "********** END OF TRANSCRIPT **********`f", 0, 'SimpleMatch'
  • -ne ''从结果中过滤掉空行块(如果文件以分隔符结尾,-split会将其后的空字符串视为另一个元素)。
  • 延迟绑定脚本块与Set-Content一起使用,以动态确定每个结果行块的输出文件名。
  • 注意$nr(输出文件序列号)是如何定义为hashtable@{ ... })的,而不是直接定义为整数;这是必需的,因为delay-bind脚本块在调用者的 * child * 作用域中运行;参见this answer以获得解释。
  • -f运算符用于合成输出文件名。

至于你所尝试的
我尝试了以下变体:'**********\s\s[END OF TRANSCRIPT]***********+\f'
只有. NET * regex引擎 *(由PowerShell的regex运算符在后台使用)才能理解\s\f等结构
因此,要使用类似上面的操作,必须使用基于正则表达式的-match操作符,而不是-eq操作符。
然而,PowerShell * 确实 * 有用于某些ASCII范围控制字符的转义序列(但 * 没有 * 用于 * 抽象 *,如\s,以表示各种空白字符),这需要使用可扩展(双引号)字符串("...")和 * 反记号 *(```)转义序列,如"f"`用于FF;在现代PowerShell (Core) 7+ edition中,还可以使用转义序列表示任何Unicode字符-请参见about_Special_Characters概念帮助主题

相关问题