从文件中删除一行.Powershell



我知道这个主题有类似的问题,但没有一个真正按照我想要的方式回答问题。

我的代码:

$answer = 1
DO {
Write-host "What u want?"
Write-host "1.Add note"
Write-host "2.Read notes"
Write-host "3.Exit"
$answer = Read-host Write a number between 1 to 3 and press Enter.
if ($answer -eq 1) 
{
DO {  
$msg = Read-host Write the note and press Enter:
$path = Get-Location 
Add-content $path"DONTREMOVEME.txt" "- $msg"
$res = Read-host "Added, want to add one more? y/n"
} 
while ($res -ne "n")
Write-host "...back to the main menu"
Start-Sleep -s 2
}
if ($answer -eq 2) 
{
$path = Get-Location 
Get-content $path"DONTREMOVEME.txt" 
Read-host "Press Enter to go back to the main menu"
}
} While ($respuesta -ne 3) 
Write-host Bye.

我真的需要添加一个";删除注释";选项,但我没有线索,并尝试了sed,grep,获取内容替换等

我需要表中的一个选项,在显示可用列表(可能有cat?(后,要求用户提供一个想要删除的注释(行((不是空白,删除(。

类似于:

if ($answer -eq 3) #let's say 'Exit' is now 4th option
{
$path = Get-Location 
Get-content $path"DONTREMOVEME.txt" # or cat $path"DONTREMOVEME.txt"
$delete = Read-host which note you want removed? Type the number and press Enter
#and actually deleting it.
}

事先非常感谢。

*编辑:我很抱歉,也许我解释得很糟糕。

我不希望代码检查用户给出的匹配字符串(这就是为什么之前关于堆栈溢出的问答实际上对我不起作用(。

DONTREMOVEME.txt中的注释可能是例如:

- Buy salt
- Buy bags
- Remember to feed cats
- Go for a walk

代码必须显示这一点,并询问用户要删除哪一行(因为它已经完成了活动(作为int。

因此用户按下";3〃;和Enter;记得喂猫"像这样消失:

- Buy salt
- Buy bags
- Go for a walk

搜索匹配的字符串不起作用,因为注释的多样性和扩展性可能会使确定一个单词并确保它不会出现在另一行中变得困难。。。

此外,不能对每一行都使用$count++,这样用户就可以使用它来匹配这样的字符串:

1 Buy salt
2 Buy bags
3 Remember to feed cats
4 Go for a walk

因为在笔记中可以写";买两个袋子";。

我希望这次我说清楚了,我对造成的麻烦感到抱歉。

我将使用注释的数组索引,而不是使用注释的某些部分来删除它。这样,用户可以输入一个数字,该功能将从列表中删除具有该索引的项目。

因为用Get-Content得到的普通数组有固定的大小,所以很难从中删除一个元素。下面使用List对象可以更容易地删除。

此外,请记住,Read-Host总是返回一个字符串(可能是数字(。。

我建议使用switch来代替所有这些if {..}语句。

类似这样的东西:

$notePath = Join-Path -Path (Get-Location) -ChildPath "DONTREMOVEME.txt"
# use a Here-String to build the menu
$mainMenu = @"
What do you want to do?
1 - Add a note
2 - Read the notes
3 - Delete a note
Q - Quit
"@
# enter an endless loop
while ($true) {
Clear-Host
Write-Host $mainMenu
$answer = Read-host "Write a number between 1 to 3 and press Enter"
Clear-Host
switch ($answer[0]) {   # [0] because we're only interested in the first character
'Q'  {
Write-host "Bye."
return
}
'1' {
do {  
$msg = Read-host "Write the note and press Enter"
Add-content -path $notePath -Value "- $msg"
$answer = Read-host "Added, want to add one more? y/n"
} 
while ($answer -ne "n")
break
}
'2' {
Get-Content $notePath
Write-Host
Read-host "Press Enter to go back to the main menu"
break
}
'3' {
# deleting from a normal array is hard to do. This is why we make use of a List object for this
$notes = [System.Collections.Generic.List[string]]@(Get-Content $notePath)
# display the notes from the file and add a number in front
for ($i = 1; $i -le $notes.Count; $i++) {
'{0,3} {1}' -f $i, $notes[$i -1]   # {0,3} adds leading spaces to the number, in total 3 digits in this example
}
Write-Host
$answer = Read-host "Press the number of the note to delete, then press Enter"
# test if the user entered a number or not
if ($answer -notmatch 'D') {
$index = [int]$answer - 1
if ($index -ge 0 -and $index -lt $notes.Count) {
# we have a valid index, remove that line and write the remaining notes to file
$notes.RemoveAt($index)
$notes | Set-Content -Path $notePath
}
}
$notes.Clear()     
}
}
Write-host "...back to the main menu"
Start-Sleep -Seconds 2
}

p.S.如果变量$answer中没有数字以外的字符,则$answer -notmatch 'D'的正则表达式。换句话说,所有字符都必须是数字

继续我的评论。

如前所述,要在文件中提取特定字符串,可以使用Out-GridView,如下所述:

  • https://practicalpowershell.com/get-out-gridview
  • https://voiceofthedba.com/2017/01/18/using-out-gridview-to-pick-parameters-sqlnewblogger

。。。或者在文件上使用Select-Stringcmdlet,然后删除或添加该点的数据。

Get-Content -Path 'D:Tempbook1.txt'
# Results
<#
Site,Dept
Main,aaa,bbb,ccc
Branch1,ddd,eee,fff
Branch2,ggg,hhh,iii
#>
Select-String -Path 'D:Tempbook1.txt' -Pattern '.*ggg.*'
# Results
<#
D:Tempbook1.txt:4:Branch2,ggg,hhh,iii
#>

注意,你不仅可以得到字符串模式,还可以得到它所在的行,因此,正如@santiago squarzon所建议的,不需要这样做:

'。。。添加一个";行号";在每行之前,这样输入可以是一个整数

然后您就可以通过该行号获得行,而无需付出任何努力。然而,PowerShell提供了几种方法来执行X或Y。因此,这里有一个结合Select String和Get Content来查找和替换文件中的内容的示例。

要修改的目标文件中有什么

Get-Content -Path 'D:Tempbook1.txt'
# Results
<#
Site,Dept
Main,aaa,bbb,ccc
Branch1,ddd,eee,fff
Branch2,ggg,hhh,iii
#>

提供目标字符串以对采取行动

Select-String -Path 'D:Tempbook1.txt' -Pattern '.*ggg.*'
# Results
<#
D:Tempbook1.txt:4:Branch2,ggg,hhh,iii
#>

注意,你不仅可以得到字符串模式,还可以得到它所在的行,因此,正如@santiago squarzon所建议的,不需要这样做:'。。。添加一个";行号";在每行之前,这样输入可以是一个整数

即使您选择不这样做,您仍然可以使用Context开关/参数来获得匹配的行。例如

Select-String -Path 'D:Tempbook1.txt' -Pattern '.*ggg.*' -Context 0
# Results
<#
D:Tempbook1.txt:4:Branch2,ggg,hhh,iii
#>

现在,如果需要用say null替换那一行,那么这个。注意,我使用RegEx来删除不需要的文件路径和行号文本。

$StringToReplace  = ((Select-String -Path 'D:Tempbook1.txt' -Pattern '.*aaa.*' -Context 0) -replace '.*:d+:')
$ReplacementString = 'null,null,null,null'
Set-Content -Path 'D:Tempbook1.txt' -Value ((Get-Content -Path 'D:Tempbook1.txt') -replace $StringToReplace, $ReplacementString)
Get-Content -Path 'D:Tempbook1.txt'
# Results
<#
Site,Dept
Main,aaa,bbb,ccc
Branch1,ddd,eee,fff
null,null,null,null
#>

同样,通过Out-GridViewcmdlet以图形方式对用户来说更容易。他们只是简单地过滤,做出选择,然后点击OK,然后你的代码处理类似于上面的选择。同样,有多种方法可以做到这一点。

最新更新