用于从文件夹中的文件中删除文本行的Powershell脚本
我们有一个程序,可以创建电子邮件签名并将其存储在部署文件夹中,然后在用户登录时保存到用户本地文件夹中。但是,如果员工未被分配到办公室,则城市/州的逗号分隔符仍会出现在乘坐过程中,如本例所示: 问题是找不到程序源代码。从长远来看,我会重写它。短期来说,我需要一个powershell脚本,它将每晚运行以删除包含逗号的行。在Stackoverflow上找到以下解决方案:用于从文件夹中的文件中删除文本行的Powershell脚本,powershell,Powershell,我们有一个程序,可以创建电子邮件签名并将其存储在部署文件夹中,然后在用户登录时保存到用户本地文件夹中。但是,如果员工未被分配到办公室,则城市/州的逗号分隔符仍会出现在乘坐过程中,如本例所示: 问题是找不到程序源代码。从长远来看,我会重写它。短期来说,我需要一个powershell脚本,它将每晚运行以删除包含逗号的行。在Stackoverflow上找到以下解决方案: Get-ChildItem C:\temp\emailsigs -Filter *.htm | Foreach-Object{ (
Get-ChildItem C:\temp\emailsigs -Filter *.htm | Foreach-Object{
(Get-Content $_.FullName) |
Foreach-Object {$_ -replace " , , <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 ' , , <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
}
}
是PSv3+,将整个文件作为单个字符串读取-Raw
- 在PSv2中,您可以使用
代替,但请注意,在没有BOM的情况下,它假定UTF-8作为编码,而[System.IO.File]::ReadAllText()
假定“ANSI”编码[1] (系统的遗留“ANSI”代码页),因此您可能必须明确指定编码获取内容
- 在PSv2中,您可以使用
- 将每个文件作为单个字符串处理可以加快处理速度(尽管每个文件必须放入内存两次)。利用
在正则表达式不匹配时保留未修改的输入字符串,我们可以将原始内容的长度与替换内容的长度进行比较,以查看是否有匹配的内容,因此需要重写文件。-replace
因此,每个文件只需要一个正则表达式操作- 还要注意,
——即不指定替换字符串——相当于-替换“…”
,即有效地删除匹配的内容-替换“…”和“
- 还要注意,
需要PSv5+;它可以防止在输出上追加额外的换行符-非WLINE
- 在PSv4-中,您可以使用
,但请注意,它的默认编码是不带BOM的UTF-8,而[System.IO.File]::writealText()
,如设置内容
,默认为“ANSI”编码[1]获取内容
- 在PSv4-中,您可以使用
[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 '* , , <br />*')
{
$Content.Replace(' , , <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)。