【问题标题】:Search folder find string between two strings in multiple files and output to a new file搜索文件夹在多个文件中的两个字符串之间查找字符串并输出到新文件
【发布时间】:2015-08-12 19:05:52
【问题描述】:

示例文本

台式机硬盘 (S/N:9VMJ31W0)

我想在文件中查找文本

9VMJ31W0

附加示例文本

服务器硬盘 (S/N:3NM2Y5HB)
服务器硬盘 (S/N:3NM2YXBD)
服务器硬盘 (S/N:6SD1MZFE)
服务器硬盘 (S/N:3NM2YX1Q)
服务器硬盘 (S/N:6SD1E8SA)
服务器硬盘 (S/N:3NM305ZQ)
服务器硬盘 (S/N:B365P760VG2F)
服务器硬盘 (S/N:B365P760VG54)

我希望输出文件读取类似这样的内容

3NM2Y5HB
3NM2YXBD
6SD1MZFE
3NM2YX1Q
6SD1E8SA
3NM305ZQ
B365P760VG2F
B365P760VG54

然后最好将其输出到 PowerShell 中的文件。

文件将位于特定文件夹中,搜索子文件夹会很棒但不是必需的。 输出将是一个多行的 .txt 文件。

有人有我可以用来执行此操作的示例文件吗?我发现了很多类似的东西,但我无法真正完成整个任务。

#Clear output variable
$Output = @()

#Get your files
$Files = Get-ChildItem -Recurse -Path "*" -Exclude "Output.txt"

#Loop through files
$Files | ForEach-Object {
  #Use Regular expression to match the desired serial number string
  $Matched = Get-Content $_.FullName | Select-String -AllMatches 'S\/N:([A-Za-z0-9]*)'

  #Loop through the matched strings
  $Matched | ForEach-Object {
    #Save to $Output the grouped (inner) string i.e. you want "9VMJ31W0" not "S/N:9VMJ31W0"
    $Output += $_.Matches.Groups.Value
  }
}

#Write output to file
$Output | Out-File Output.txt

【问题讨论】:

  • 你有什么例子吗?
  • 添加了我到目前为止的内容。

标签: powershell


【解决方案1】:

在处理字符串时,稍微搜索了一下,我发现了 powershell 的 SubString 方法。有关字符串的更多信息,请参阅this page

PS C:\Scripts\updates> $f = gc C:\Scripts\p.txt

PS C:\Scripts\updates> $f
DESKTOP HARD DRIVE (S/N:9VMJ31W0)
DESKTOP HARD DRIVE (S/N:9VMJ31W1)
DESKTOP HARD DRIVE (S/N:9VMJ31W2)

PS C:\Scripts\updates> $f | GM
(Truncated)
Substring        Method                string Substring(int startIndex), str

PS C:\Scripts\updates> $f.substring(24,8) | out-file C:\Temp\HDDSerials.txt

PS C:\Scripts\updates> Get-Content C:\Temp\HDDSerials.txt
9VMJ31W0
9VMJ31W1
9VMJ31W2

【讨论】:

    【解决方案2】:

    对于初学者,这将输出 "D:\MyFolder" 和子文件夹 (-Recurse) 中所有文件中包含 "DESKTOP HARD DRIVE" 的所有行,并将它们附加到 "D:\MyFolder\Output.txt" .

    Get-ChildItem -Recurse -Path "D:\MyFolder" -Exclude "Output.txt" |
    % {Get-Content $_.FullName | Where-Object {$_ -like '*DESKTOP HARD DRIVE*'} |
    Select-Object} | Out-File "D:\MyFolder\Output.txt"
    

    最好将输出发送到单独的文件夹,或使用 -Exclude 将其排除在处理之外。

    【讨论】:

      【解决方案3】:

      正则表达式是执行此操作的方法,因为序列号在文件中的位置无关紧要,它会找到它:

      #Clear output variable
      $Output = @()
      
      #Get your files
      $Files = Get-ChildItem -Recurse -Path "*" -Exclude "Output.txt"
      
      #Loop through files
      $Files | ForEach-Object {
          #Use Regular expression to match the desired serial number string
          $Matched = Get-Content $_.FullName | Select-String -AllMatches 'S\/N:([A-Za-z0-9]*)'
      
          #Loop through the matched strings
          $Matched | ForEach-Object {
              #Save to $Output the grouped (inner) string i.e. you want "9VMJ31W0" not "S/N:9VMJ31W0"
              $Output += $_.Matches.Groups[1].Value
          }
      }
      
      #Write output to file
      $Output | Out-File Output.txt
      

      如果您想更具体地匹配“DESKTOP HARD DRIVE (S/N:9VMJ31W0)”而不是只是“S/N:9VMJ31W0”,那么您将匹配更改为:

      Select-String -AllMatches 'DESKTOP HARD DRIVE \(S\/N:([A-Za-z0-9]*)\)'
      

      【讨论】:

      • 我尝试了这个但是我没有得到任何输出,你有什么建议吗?
      • 我无法让它与您提供的代码一起使用。我从组中删除了 [1] 并让它运行但是我没有得到任何结果。
      • 确保您在拥有该文件的同一文件夹中运行此代码。我用您的示例文本创建了一个文本文件,将其保存到 C:\temp。我将 powershell 目录更改为 C:\temp,然后运行上面的代码并能够提取所有序列号。检查 $Files 变量。确保它具有您正在运行的文件
      【解决方案4】:

      这是一个单行:

        Select-String -Path C:\temp\files\*.txt -Exclude output.txt -Pattern '(?<=S/N:)\w+(?=\))' -AllMatches | 
      Select-Object -ExpandProperty matches | 
          Select-Object -ExpandProperty Value |
              Out-File -FilePath C:\temp\files\output.txt -Append 
      

      使用lookbehind 查找S\N: 之后的文本,并使用lookahead 查找末尾大括号)

      注意:这假设您的文本存储在文本文件*.txt

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-15
        • 2012-05-18
        • 1970-01-01
        • 1970-01-01
        • 2016-10-09
        • 1970-01-01
        相关资源
        最近更新 更多