การลบทั้งบรรทัดในไฟล์ข้อความโดยอิงจากสตริงบางส่วนที่ตรงกับ Windows PowerShell


22

ดังนั้นฉันจึงมีไฟล์ข้อความขนาดใหญ่หลายไฟล์ที่ฉันต้องการจัดเรียงและลบบรรทัดทั้งหมดที่มีคำหลักที่ระบุ ดังนั้นโดยทั่วไปถ้าฉันมีเส้นเหล่านี้:

นี่ไม่ใช่การทดสอบ
นี่เป็นการทดสอบ
อาจเป็นการทดสอบ
ไม่ใช่การทดสอบแน่นอน

และฉันรันสคริปต์ด้วย 'ไม่' ฉันต้องลบบรรทัดที่ 1 และ 4 ทั้งหมด

ฉันเคยลอง:

PS C:\Users\Admin> (Get-Content "D:\Logs\co2.txt") | 
Foreach-Object {$_ -replace "3*Program*", ""} | 
Set-Content "D:\Logs\co2.txt"

แต่จะแทนที่ 'โปรแกรม' เท่านั้นไม่ใช่ทั้งบรรทัด

คำตอบ:


25

นี่คือสิ่งที่ฉันจะทำ:

Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt

บรรทัดของ Snarkทำเช่นเดียวกัน แต่เริ่มต้นด้วยการโหลดไฟล์ทั้งหมดลงในอาร์เรย์ซึ่งอาจมีปัญหากับไฟล์หน่วยความจำขนาดใหญ่ที่ชาญฉลาด


ฉันขอแนะนำให้คุณใช้ Set-Content แทน Out-File ข้อตกลงเดิมในข้อมูลดิบและจะไม่ตัดสตริงหรือวัตถุรูปแบบ
JasonMArcher

@JasonMArcher คุณช่วยโพสต์ตัวอย่างได้Set-Contentไหม? ผมไม่เชื่อว่าเป็นแบบเลื่อนแทนSet-Content Out-File
เลนซามูเอลแมคลีนผู้อาวุโส

Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt Out-File นั้นเป็นชุดเนื้อหา แต่จะเรียกใช้อินพุตผ่านการจัดรูปแบบเริ่มต้นแทนการแปลงสตริงอย่างง่าย
JasonMArcher

ฉันมีปัญหาเดียวกันที่แน่นอนและคุณตอบว่า 99% ของสิ่งที่ฉันต้องการ ปัญหาสุดท้ายคือฉันกำลังใช้คำสั่งในการวนกับ $ ตัวแปร (แทนที่ 'ไม่' ในตัวอย่างของคุณ) ถ้าฉันรหัสยากสตริงมันทำงานได้อย่างสมบูรณ์; แต่ถ้าฉันใช้ตัวแปรมันไม่ทำอะไรเลย มีความคิดอะไรบ้าง ฉันได้พยายามทั้งสองตัวแปรเปลือยและวางไว้ใน "คำพูด"
สตีเฟ่น R

วิธีนี้สามารถแก้ไขเพื่อแทนที่ข้อความในบรรทัดเหล่านั้น
Tom

7

สิ่งนี้จะได้ผล:

(Get-Content "D:\Logs\co2.txt") -notmatch "not" | Out-File "D:\Logs\co2.txt"

นี่จะส่งคืนบรรทัดเดียวในไฟล์ที่สองที่ชื่อว่า True

การแก้ไข: นี่จะส่งคืนบรรทัดเดียวในไฟล์ที่สองซึ่งประกอบด้วย 'True' มันอาจจะหายไป "Foreach-Object {$ _" ดังนั้นมันจะทำงานหนึ่งครั้งต่อบรรทัดหรือไม่? แก้ไข: จริง ๆ แล้วมันไม่เกี่ยวข้องตอนนี้มันลบไฟล์ที่ฉันหวังว่าจะล้าง ขอบคุณสำหรับความช่วยเหลือต่อไป แต่ฉันยังคงสงสัยว่าคำสั่งที่ถูกต้องจะเป็นอย่างไรฉันจึงสามารถทำสิ่งนี้ได้ในอนาคต

1
มันใช้งานได้สำหรับฉันกับ 4 สายการทดสอบของคุณด้านบน
Snark

2
จะไม่ได้เขียนทับไฟล์ต้นฉบับ!
user33788

3
เห็นด้วย แต่ฉันใช้ชื่อไฟล์เดียวกับที่ใช้กับโปสเตอร์ดั้งเดิมเพื่อให้คำตอบง่ายขึ้น เขาใช้ co2.txt สำหรับทั้งอินพุตและเอาต์พุต
Snark

0

คุณยังสามารถใช้ 'เลือกสตริง' กับตัวเลือก -notmatch:

Select-String 'not' .\input.txt -notmatch | % {$_.Line} | set-content output.txt

0

ฉันแค่ต้องการทำงานนี้และทำสิ่งต่อไปนี้:

$InServerName = 'SomeServerNameorIPAddress'
$InFilePath = '\Sharename\SomePath\'
$InFileName = 'Filename.ext'

$OutServerName = 'SomeServerNameorIPAddress'
$OutFilePath = '\Sharename\SomePath\'
$OutFileName = 'Filename.out'

$InFile = -join('\\',$InServerName,$InFilePath,$InFilename)
$OutFile = -join('\\',$OutServerName,$OutFilePath,$OutFilename)
$FindStr = 'some string to match on'
$CompareStr = [scriptblock]::Create($FindStr)
$CompareStr
Get-Content $InFile | Where-Object {$_ -notmatch $CompareStr} | Set-Content $OutFile
Get-Content $OutFile

กุญแจสำคัญคือ 'Where-Object' ที่ใช้บล็อกสคริปต์ (ดังแสดงด้วยเครื่องหมายปีกกา) ต้องประกาศตัวแปรในเหตุการณ์การสร้างบล็อกสคริปต์ดังนั้น

$CompareStr = [scriptblock]::Create($FindStr)

ไลน์.

ด้วยการจัดโครงสร้างด้วยวิธีนี้เราสามารถสร้างฟังก์ชั่นส่งผ่านสตริงข้อความเพื่อจับคู่บางส่วนดำเนินการสร้างบล็อกสคริปต์ด้วยค่าที่ส่งผ่านและทำให้มันทำงานอย่างถูกต้อง

คำตอบข้างต้นไม่ถูกต้องอธิบายวิธีส่งผ่านค่าที่จะถูกแทนที่ภายในตัวแปร


คุณช่วยอธิบายให้ชัดเจนกว่านี้ได้อย่างไรดีกว่าคำตอบที่กระชับกว่าSnark ? กรุณาอย่าตอบในความคิดเห็น; แก้ไขคำตอบของคุณเพื่อให้ชัดเจนและสมบูรณ์ยิ่งขึ้น
สกอตต์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.