用于从文件夹中的文件中删除文本行的Powershell脚本

用于从文件夹中的文件中删除文本行的Powershell脚本,powershell,Powershell,我们有一个程序,可以创建电子邮件签名并将其存储在部署文件夹中,然后在用户登录时保存到用户本地文件夹中。但是,如果员工未被分配到办公室,则城市/州的逗号分隔符仍会出现在乘坐过程中,如本例所示: 问题是找不到程序源代码。从长远来看,我会重写它。短期来说,我需要一个powershell脚本,它将每晚运行以删除包含逗号的行。在Stackoverflow上找到以下解决方案: Get-ChildItem C:\temp\emailsigs -Filter *.htm | Foreach-Object{ (

我们有一个程序,可以创建电子邮件签名并将其存储在部署文件夹中,然后在用户登录时保存到用户本地文件夹中。但是,如果员工未被分配到办公室,则城市/州的逗号分隔符仍会出现在乘坐过程中,如本例所示:

问题是找不到程序源代码。从长远来看,我会重写它。短期来说,我需要一个powershell脚本,它将每晚运行以删除包含逗号的行。在Stackoverflow上找到以下解决方案:

Get-ChildItem C:\temp\emailsigs -Filter *.htm | Foreach-Object{
(Get-Content $_.FullName) | 
Foreach-Object {$_ -replace " ,   &nbsp; ,   &nbsp; <br />", ""} | 
Set-Content $_.FullName
}
Get ChildItem C:\temp\emailsigs-Filter*.htm | Foreach对象{
(获取内容$\.FullName)|
Foreach对象{$\替换“,
,”“} 设置内容$\u0.FullName }

这实际上效果很好。但我注意到,每个签名HTM文件(超过1100个)都会得到时间戳更新,即使只有2个电子邮件签名需要删除空逗号行。是否有更有效的方法首先检查文件是否包含有问题的逗号,然后替换并跳过大多数?

以下PSv5+解决方案不会节省内存,但应加快处理速度,同时避免重写不需要它的文件:

Get-ChildItem C:\temp\emailsigs -Filter *.htm |
  ForEach-Object {
    $oldContent = Get-Content -Raw $_.FullName
    $newContent = $oldContent -replace ' ,   &nbsp; ,   &nbsp; <br />'
    if ($newContent.Length -lt $oldContent.Length) { # was a replacement performed?
      Set-Content $_.FullName -NoNewline -Value $newContent
    }
  }
Get ChildItem C:\temp\emailsigs-Filter*.htm|
ForEach对象{
$oldContent=Get Content-Raw$\.FullName
$newContent=$oldContent-替换“,
” 如果($newContent.Length-lt$oldContent.Length){#是否执行了替换? 设置Content$\ FullName-NoNewline-Value$newContent } }
  • -Raw
    是PSv3+,将整个文件作为单个字符串读取

    • 在PSv2中,您可以使用
      [System.IO.File]::ReadAllText()
      代替,但请注意,在没有BOM的情况下,它假定UTF-8作为编码,而
      获取内容
      假定“ANSI”编码[1] (系统的遗留“ANSI”代码页),因此您可能必须明确指定编码
  • 将每个文件作为单个字符串处理可以加快处理速度(尽管每个文件必须放入内存两次)。利用
    -replace
    在正则表达式不匹配时保留未修改的输入字符串,我们可以将原始内容的长度与替换内容的长度进行比较,以查看是否有匹配的内容,因此需要重写文件。
    因此,每个文件只需要一个正则表达式操作

    • 还要注意,
      -替换“…”
      ——即不指定替换字符串——相当于
      -替换“…”和“
      ,即有效地删除匹配的内容
  • -非WLINE
    需要PSv5+;它可以防止在输出上追加额外的换行符

    • 在PSv4-中,您可以使用
      [System.IO.File]::writealText()
      ,但请注意,它的默认编码是不带BOM的UTF-8,而
      设置内容
      ,如
      获取内容
      ,默认为“ANSI”编码[1]

[1] 以上内容适用于Windows PowerShell。跨平台版本也默认为(无BOM)UTF-8。

其他方法

Get-ChildItem C:\temp\emailsigs -file -Filter *.htm | foreach{

$CurrentFile=$_

$Content=Get-Content $CurrentFile.FullName -Encoding UTF8

if ($Content -like '* ,   &nbsp; ,   &nbsp; <br />*')
{
    $Content.Replace(' ,   &nbsp; ,   &nbsp; <br />', '') | Set-Content $CurrentFile.FullName -Encoding UTF8
}

}
Get ChildItem C:\temp\emailsigs-file-Filter*.htm | foreach{
$CurrentFile=$_
$Content=获取内容$CurrentFile.FullName-编码UTF8
如果($内容-如“*,
*”) { $Content.Replace(',
','')|设置内容$CurrentFile.FullName-编码UTF8 } }

我使用utf8来保留发音符号

我确认htm文件未被其他程序使用。我怀疑这个脚本过程会锁定文件。因此,我不得不奖励第二个解决方案。@user3195770:是的,是我原始答案中的
Get Content
锁定了每个输入文件,阻止了它的替换。然而,我几小时前发布的修订版通过使用
getchilditem
避免了这个问题。它仍然具有只匹配一次文件内容的优势,并且由于将文件作为单个字符串处理,因此通常速度更快(此外,我刚刚添加了另一个优化,仅比较内容长度以确定是否进行了替换)。很酷,我将尝试在几分钟内进行测试。希望我能同时给出两个答案。@user3195770:明白:一般来说,如果多个答案都能同样地解决你的问题(希望不是以完全相同的方式,因为那样会使答案重复),我建议接受最有可能帮助未来读者的答案。为了表示对其他人的感激,你通常会给他们投票,但还没有足够的声望(要求>=15)。