您所期望的和您尝试过的代码有很多错误,所以让我们分解它并找到解决方案。感谢您自己尝试此操作。首先,这是解决方案,请阅读以下代码以了解您做错了什么以及如何获得我编写的代码:
# Get matching lines plus the following line from the example.txt seed file
$seedMatches = Select-String -Path .\example.txt -Pattern "6,\s*16" -Context 0, 2
# Obtain the ID number from the line following each match
$idNumbers = foreach( $match in $seedMatches ) {
$postMatchFields = $match.Context.PostContext -split ":\s*"
# Note: .IndexOf(object) is case-sensitive when looking for strings
# Returns -1 if not found
$idFieldIndex = $postMatchFields.IndexOf("ID number")
# Return the "ID number" to `$idNumbers` if "ID number" is found in $postMatchFields
if( $idFieldIndex -gt -1 ) {
$postMatchFields[$idFieldIndex + 1]
}
}
# Match lines in export.txt where both the $id and "6,16" appear
$exportMatches = foreach( $id in $idNumbers ) {
Select-String -Path .\export.txt -Pattern "^(?=.*\b$id\b)(?=.*\b6,\s*16\b).*$"
}
mklement0's answer 基本上将其压缩为更少的代码,但我想将其完全分解。
首先,Select-String -Path ".\*.txt" 将查看当前目录中的所有.txt 文件。您需要将其缩小到您在种子文件中寻找的特定命名模式(我们想要在其他文件中查找要查找的 ID 的文件)。对于此示例,我将使用 example.txt 和 export.txt 作为您在问题中其他地方使用的路径,而不使用通配符来匹配文件名。
接下来,-Context 给出了比赛中周围线条的上下文。您只关心下一行匹配,因此 0, 1 应该足以满足 -Context(匹配前 0 行,匹配后 1 行)。
最后,我将\s* 添加到-Pattern 以匹配空格,如果16 曾经从, 填充。所以现在我们准备好了Select-String 命令:
$seedMatches = Select-String -Path .\example.txt -Pattern "6,\s*16" -Context 0, 2
接下来,我们需要遍历种子文件中的匹配结果。您可以使用foreach 或ForEach-Object,但我将在下面的示例中使用foreach。
对于$seedMatches 中的每个$match,我们需要从每个匹配项之后的行中获取$idNumbers。当$match 是ToString()'d 时,它会吐出匹配的行和任何周围的上下文行。由于我们的上下文匹配后只有一行,因此我们可以为此获取 $match.Context.PostContext。
现在我们可以获得$idNumber。我们可以通过使用-split 操作符将:\s* 模式上的字符串拆分(\s* 匹配任何或不匹配空格)将example.txt:5218: ID number:0002743284 拆分为字符串数组。一旦我们有了这个,我们就可以得到“ID号”的索引,并得到紧随其后的字段的值。现在我们有了$idNumbers。我还将在下面添加一些保护措施,以确保在继续之前确实找到了 ID numbers 字段。
$idNumbers = foreach( $match in $seedMatches ) {
$postMatchFields = $match.Context.PostContext -split ":\s*"
# Note: .IndexOf(object) is case-sensitive when looking for strings
# Returns -1 if not found
$idFieldIndex = $postMatchFields.IndexOf("ID number")
# Return the "ID number" to `$idNumbers` if "ID number" is found in $postMatchFields
if( $idFieldIndex -gt -1 ) {
$postMatchFields[$idFieldIndex + 1]
}
}
现在我们有了$idNumbers,我们可以在export.txt 中查找同一行中的ID 号“6,\s*16”,再次使用Select-String。这一次,我先把代码放在前面,因为它不是什么新鲜事,然后解释一下正则表达式:
$exportMatches = foreach( $id in $idNumbers ) {
Select-String -Path .\export.txt -Pattern "^(?=.*\b$id\b)(?=.*\b6,\s*16\b).*$"
}
$exportMatches 现在将包含在同一行上同时包含目标 ID number 和 6,16 值的行。请注意,未指定顺序,因此表达式使用positive lookaheads 来查找$id 和6,16 值,而不管它们在字符串中的顺序如何。我不会分解确切的表达式,但如果您将^(?=.*\b0123456789\b)(?=.*\b6,\s*16\b).*$ 插入https://regexr.com,它将分解并详细解释正则表达式模式。
完整代码在上面at the top of this answer。