【问题标题】:Powershell - need to parse a text file and past into emailPowershell - 需要解析一个文本文件并过去到电子邮件中
【发布时间】:2016-06-28 02:12:44
【问题描述】:

我有一个包含用户名的非常基本的文本文件。我需要能够搜索以“User bsmith”开头的每个部分(例如),复制后面的所有文本并在下一个“User XXXX”(用户 tford,例如下面)之前的行结束。然后,我会将复制的文本粘贴到电子邮件正文中。我已经编写了 Powershell 来创建电子邮件并发送它。我只需要编写部分来从列出的文本文件中获取文本。编程还是新手,因此很难确定从 .txt 文件中搜索和复制并粘贴到电子邮件正文中的方式。 svnlog.txt 是被解析的文件。我可以获取所有内容,但需要能够搜索每个“用户 XXXX”到下一个“用户 XXX”的部分。

$olComObject = new-object -comobject outlook.application
$svn = (Get-Content C:\Dev\Powershell\svnlog.txt) -join "`n"
$NewMail = $olComObject.CreateItem(0)
$NewMail.Subject = "Testing Voting Options"
$NewMail.Body = "Please use the attached voting buttons in this email to acknowledge or reject if the following user permissions are correct!" + "`n" +  $svn
$NewMail.To = "bsmith@company.com;tford@company.com"
$NewMail.VotingOptions = "Accept;Reject"
$NewMail.Send()

我正在考虑使用以下方法搜索单个“用户 XXX”组,但我再次不确定这是否是正确的路径,甚至是否可行。

$fullsvn = Get-Content "C:\Dev\Powershell\svnlog.txt"
Out-File () "C:\Dev\Powershell\svnlogBSmith.txt"

文本文件内容格式如下。

用户 BSmith

回购

[功能规格:/]

@admins = rw

@dba = r

@hca = rw

@businessAnalysts = rw

@qa = rw

@portal = rw

@intercept = rw

@pmo = rw

[restrictedDocs:/softtek]

@restrictedDocs = rw

BusinessAnalysts = ajones, pjohnson, ssmith, rjackson,

@pmo = 弗格森

用户 tford

好的。所以我尝试了 TessellatingHeckler 的路线。但是,它似乎没有用用户名标记行(在这种情况下,它是 TKelems 而不是 BSmith)。这是我当前的代码和我在控制台中获得的输出示例。

Get-Content C:\Dev\Powershell\svnlog.txt | foreach {
     if ($_ -match '^User (.*)') {
         $tag = $matches[1]
         }

         [Management.Automation.PSObject]@{
             Tag=$tag
             Item=$_
         }
     }

$TKelems | Where Tag -EQ 'tkelems'

Out-File "C:\Dev\Powershell\svnlogTKelems.txt" -InputObject $TKelems

输出:

名称值
---- -----
标记
物品 - - - - - - - - - - - - - - - - - - - - - - - - - -------------------------------------------
标记
项目用户
标记
物品 tkelems:
标记
项目
标记
项目回购
标记
项目 --------------------
标记
项目 [功能规格:/]
标记
项目@admins = rw
标记
项目@eclas = rw
标记
项目@cfis = rw
标记
项目@transMgmt = rw
标记
项目@dba = r
标记
项目@hca = rw
标记
项目@businessAnalysts = rw
标记
项目@qa = rw
标记
项目@portal = rw
标记
项目@intercept = rw
标记

我也忘记添加在最后一行创建的 Ou-File 的内容。也不知道该怎么做。基本上,控制台中没有显示任何标签,输出文件显示完全不同的东西(见下文):

IsReadOnly : 假

IsFixedSize : 假

IsSynchronized : 假

键:{标签,项目}

值:{$null, ----------------------------------------- ---------------------------------------}

SyncRoot : System.Object

计数:2

IsReadOnly : 假

IsFixedSize : 假

IsSynchronized : 假

键:{标签,项目}

值:{$null, 用户}

SyncRoot : System.Object

计数:2

【问题讨论】:

  • 请跳过文本文件
  • 您没有在脚本中的任何位置分配$TKelems...它甚至有任何内容吗?写第一行$TKelems = Get-Content ... | Foreach { 试试看。
  • 好的。谢谢。我认为在最后一行用管道处理它会解决这个问题。我试试看。
  • 这没有帮助。问题是我需要将 $TKelems 定义为带有 tkelems 标签的数据。我认为在第一行定义它不适用于文件中列出的其余“用户”。此外,我忘记添加创建的 Out-File 的内容。这已添加到帖子中。
  • 在第一行定义 $TKelems ($TKelems = gc .\log.txt) 生成包含所有值的输出。如您所见,标签键值也在那里显示为 null。不知道为什么这没有标记任何东西。

标签: email powershell svn outlook


【解决方案1】:

一个选项:

$textfile = 'c:\testfiles\test.txt'

$Search = 'BSmith'

$Found = (Get-Content $textfile -Raw) -split '(?ms)^(?=User)' -like "User $Search*"

这会将文本文件作为单个字符串读取,然后将其拆分为以“用户”开头的行,并过滤掉与 $Search 中的用户名不匹配的行。

您需要添加错误捕获以检查 $found 是否为空,或返回多个结果并处理以适应。

【讨论】:

  • 我一直期待看到您的回答。我倾向于过度思考正则表达式
  • 谢谢。多行正则表达式起初可能会令人生畏(主要是因为您没有看到很多示例),但似乎总是提供更简单的解决方案来解析多行文本一个把手。
【解决方案2】:

这样的事情可能是一个起点

$usernameregex = 'bsmith'

$found = $false
Get-Content "C:\Dev\Powershell\svnlog.txt" | % {
    if (!$found -and $_ -match "^user $username$") {
        $found = $true
        Write-Output ''
        Write-Output $_
    } elseif ($found -and $_ -match '^user ') {
        if (!($_ -match "^user $username$")) {
            $found = $false
        } elseif ($_ -match "^user $username$") {
            Write-Output ''
            Write-Output $_
        } else {
            Write-Output ''
        }
    } elseif ($found) {
        Write-Output $_
    }
} | select -skip 1 | Set-Content "C:\Dev\Powershell\svnlogBSmith.txt"

要检查多个名称,请将 $usernameregex 更改为此

$usernameregex = (bsmith|tford)

【讨论】:

    【解决方案3】:

    我之前看过这个“我希望文件中的行从 [section header] 到下一个 [section header]”,并且 mjolinor 对多行正则表达式的回答简短而有效,但是我认为这不是很清楚它在做什么以及为什么。如果不先-joining 它们,它在一般的字符串数组上也不会很好地工作。

    作为替代方案,我非常喜欢标记每一行的概念,然后您可以按标记进行分组或过滤。例如取出用户名并用最后看到的用户名标记每一行:

    gc .\log.txt | foreach { 
        if ($_ -match '^User (.*)') {
            $tag = $matches[1]
        }
    
        [pscustomobject]@{
            Tag=$tag
            Item=$_
        }
    }
    

    它对您的文件的作用是:

    Tag                    Item                                                     
    ----                   ----                                                     
    BSmith                 User BSmith                                              
    BSmith                 repos                                                    
    BSmith                 [functionalSpecs:/]                                      
    BSmith                 @admins = rw                                             
    BSmith                 @dba = r                                                 
    BSmith                 @hca = rw                                                
    BSmith                 @businessAnalysts = rw                                   
    BSmith                 @qa = rw                                                 
    BSmith                 @portal = rw                                             
    BSmith                 @intercept = rw                                          
    BSmith                 @pmo = rw                                                
    BSmith                 [restrictedDocs:/softtek]                                
    BSmith                 @restrictedDocs = rw                                     
    BSmith                 Groups                                                   
    BSmith                 BusinessAnalysts = ajones, pjohnson, ssmith, rjackson,   
    BSmith                 @pmo = lferguson                                         
    tford                  User tford                                               
    tford                               
    

    那么你就可以轻松:

    $that | Where Tag -eq 'BSmith'
    

    $that | group Tag
    

    它可以用任何正则表达式匹配部分分隔符来标记行。

    [编辑:@mjolinor 建议将^ 添加到正则表达式]

    【讨论】:

    • 这个解决方案也可以,但是如果您要处理大量行,它可能无法很好地扩展。我建议在该正则表达式中包含行锚 (^) 的开头。就目前而言,它很有可能产生意想不到的后果。字符串 'user' 很容易出现在节标题后面的任意数据中,然后你会得到意想不到的结果。恕我直言。
    • @mjolinor 我同意这两点(但 GC -Raw 是否也可以缩放很多行?这不需要在开始工作之前全部阅读)和行首锚会使它更健壮。我认为这种“extract lines from X to Y”问题的通用解决方案可能是对 Select-String 的合理补充,所以我在 PowerShell 用户语音中提出了建议:windowsserver.uservoice.com/forums/301869-powershell/…
    • 如果输入文件足够大,任何一方都将开始遭受内存耗尽的困扰,但是将每一行转换为 PS 对象会更快。我将发布的数据外推到 5000 个用户,并通过这两种解决方案运行它。将其拆分为多行字符串需要大约 12mb 的内存。将每一行渲染为一个 PS 对象几乎需要半场演出。
    • 好的。所以我尝试了 TessellatingHeckler 的路线。但是,它似乎没有将标签应用于项目。输出列出了项目,但将标签显示为空白。这是我在控制台中得到的输出。
    猜你喜欢
    • 1970-01-01
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 2018-12-01
    • 2015-05-08
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多