PowerShell - 用于更改多值字段中分隔符的正则表达式
PowerShell - regex for changing delimiter in multi-value field
我有一个制表符分隔的数据集(删除了一些列但与此处无关):
XYZ 12345671 18884 18912 222.00 222.00 Standard 2 CMD.1
ABC 12345672 18875 397.00 Standard 1 CMD.2
ABC 12345673 18889 18919 18950 146.66 146.66 146.68 Standard 3 CMD.2
XYZ 12345674 18840 18871 18901 193.00 193.00 192.00 Standard 3 CMD.1
不幸的是,在数据集中有两个多值字段(具有 1 个或多个子值)使用与其他所有列相同的分隔符。所有以18开头的5位数字都是一个字段,然后所有的十进制数都是第二个字段。子值的数量将始终在这些字段之间匹配(也就是说,如果第一个有 2 个值,第二个将有 2 个值)。 "Standard" 和 "CMD.X" 之间的 lonae 数本身就是每个字段中子值的数量。基本上,我要创建的是:
XYZ 12345671 18884;18912 222.00;222.00 Standard 2 CMD.1
ABC 12345672 18875 397.00 Standard 1 CMD.2
ABC 12345673 18889;18919;18950 146.66;146.66;146.68 Standard 3 CMD.2
XYZ 12345674 18840;18871;18901 193.00;193.00;192.00 Standard 3 CMD.1
由于文件大小,我尝试将其与 System.IO.File(多达 100,000k 条记录)一起使用:
$File = [System.IO.File]::ReadAllText('in_file.txt')
ForEach($RecordSet In $File){
$RecordSet = $RecordSet -CReplace '(?m)(/d/d/d/d/d)`t(/d/d/d/d/d)','(/d/d/d/d/d);(/d/d/d/d/d)'
$RecordSet = $RecordSet -CReplace '(?m)([0-9]*\.[0-9]+|[0-9]+)`t([0-9]*\.[0-9]+|[0-9]+)','([0-9]*\.[0-9]+|[0-9]+);([0-9]*\.[0-9]+|[0-9]+)'
Add-Content ('out_file.txt") $RecordSet
}
是的,我意识到 in_file.txt 是一种愚蠢的格式 -- 不幸的是它不可更改。
方法一
也许,
(?<=\s\d{5}\b)\s+(?=\b\d{5}\b)|(?<=\s\d{3}\.\d{2}\b)\s+(?=\b\d{3}\.\d{2}\b)
和 ;
的替代品可能可以研究一下。
Demo 1
方法二
或者您可能会捕捉到那些表达方式类似于
的人
(\d+)\s{3}(\d+)\s{3}(?:(\d+)\s{3})?(\d+\.\d+)\s{2}(\d+\.\d+)\s{2}(?:(\d+\.\d+)\s{2})?Standard
然后,替换为;;;;;;
或;;;;
。
如果您希望 simplify/modify/explore 表达式,regex101.com. If you'd like, you can also watch in this link 的右上面板已对其进行说明,它将如何匹配一些样本输入。
我有一个制表符分隔的数据集(删除了一些列但与此处无关):
XYZ 12345671 18884 18912 222.00 222.00 Standard 2 CMD.1
ABC 12345672 18875 397.00 Standard 1 CMD.2
ABC 12345673 18889 18919 18950 146.66 146.66 146.68 Standard 3 CMD.2
XYZ 12345674 18840 18871 18901 193.00 193.00 192.00 Standard 3 CMD.1
不幸的是,在数据集中有两个多值字段(具有 1 个或多个子值)使用与其他所有列相同的分隔符。所有以18开头的5位数字都是一个字段,然后所有的十进制数都是第二个字段。子值的数量将始终在这些字段之间匹配(也就是说,如果第一个有 2 个值,第二个将有 2 个值)。 "Standard" 和 "CMD.X" 之间的 lonae 数本身就是每个字段中子值的数量。基本上,我要创建的是:
XYZ 12345671 18884;18912 222.00;222.00 Standard 2 CMD.1
ABC 12345672 18875 397.00 Standard 1 CMD.2
ABC 12345673 18889;18919;18950 146.66;146.66;146.68 Standard 3 CMD.2
XYZ 12345674 18840;18871;18901 193.00;193.00;192.00 Standard 3 CMD.1
由于文件大小,我尝试将其与 System.IO.File(多达 100,000k 条记录)一起使用:
$File = [System.IO.File]::ReadAllText('in_file.txt')
ForEach($RecordSet In $File){
$RecordSet = $RecordSet -CReplace '(?m)(/d/d/d/d/d)`t(/d/d/d/d/d)','(/d/d/d/d/d);(/d/d/d/d/d)'
$RecordSet = $RecordSet -CReplace '(?m)([0-9]*\.[0-9]+|[0-9]+)`t([0-9]*\.[0-9]+|[0-9]+)','([0-9]*\.[0-9]+|[0-9]+);([0-9]*\.[0-9]+|[0-9]+)'
Add-Content ('out_file.txt") $RecordSet
}
是的,我意识到 in_file.txt 是一种愚蠢的格式 -- 不幸的是它不可更改。
方法一
也许,
(?<=\s\d{5}\b)\s+(?=\b\d{5}\b)|(?<=\s\d{3}\.\d{2}\b)\s+(?=\b\d{3}\.\d{2}\b)
和 ;
的替代品可能可以研究一下。
Demo 1
方法二
或者您可能会捕捉到那些表达方式类似于
的人(\d+)\s{3}(\d+)\s{3}(?:(\d+)\s{3})?(\d+\.\d+)\s{2}(\d+\.\d+)\s{2}(?:(\d+\.\d+)\s{2})?Standard
然后,替换为;;;;;;
或;;;;
。
如果您希望 simplify/modify/explore 表达式,regex101.com. If you'd like, you can also watch in this link 的右上面板已对其进行说明,它将如何匹配一些样本输入。