วิธีลบบรรทัดจากไฟล์ข้อความที่มีคำเฉพาะผ่านเทอร์มินัล


72

วิธีลบบรรทัดทั้งหมดออกจากไฟล์ข้อความที่มีคำว่า "cat" และ "rat"


ฟังดูน่าสงสัยเหมือนการบ้าน โปรดจำไว้ว่าให้คำตอบของคุณกับคนที่มีความสุขมากกว่าที่ Askubuntu
zwets

นั่นเป็นส่วนหนึ่งของโครงการใหญ่ฉันยังใหม่กับสภาพแวดล้อม Linux
PersonX

คำตอบ:


100

grep เข้าใกล้

หากต้องการสร้างสำเนาของไฟล์โดยไม่มีบรรทัดที่ตรงกับ "cat" หรือ "rat" ไฟล์หนึ่งสามารถใช้grepใน reverse ( -v) และด้วยตัวเลือกทั้งคำ ( -w)

grep -vwE "(cat|rat)" sourcefile > destinationfile

ตัวเลือกทั้งหมดคำทำให้แน่ใจว่าจะไม่ตรงกันcatsหรือgratefulเป็นตัวอย่าง การเปลี่ยนเส้นทางเอาต์พุตของเชลล์ของคุณถูกใช้ ( >) เพื่อเขียนไปยังไฟล์ใหม่ เราต้องการ-Eตัวเลือกในการเปิดใช้งานการแสดงออกปกติเพิ่มเติมสำหรับ(one|other)ไวยากรณ์

sed เข้าใกล้

อีกทางหนึ่งหากต้องการลบบรรทัดในตำแหน่งที่สามารถใช้ได้sed -i:

sed -i "/\b\(cat\|rat\)\b/d" filename

\bขอบเขตชุดคำและdดำเนินการลบเส้นที่ตรงกับการแสดงออกระหว่างทับไปข้างหน้า catและratทั้งคู่มีการจับคู่โดย(one|other)ไวยากรณ์ที่เราเห็นได้ชัดว่าต้องหลบหนีด้วยแบ็กสแลช

เคล็ดลับ: ใช้sedโดยไม่มี-iโอเปอเรเตอร์เพื่อทดสอบเอาต์พุตของคำสั่งก่อนเขียนทับไฟล์

(อิงจากSed - ลบบรรทัดที่มีสตริงที่ระบุ )


ฉันสงสัยว่ามีวิธีการที่จะบรรลุการลบทั้งสองจากไฟล์ต้นฉบับและสร้างไฟล์ด้วยการจับคู่ อาจไม่ได้ แต่มันจะมีประโยชน์ (เช่นเมื่อคุณได้รับไฟล์ที่มีขนาดใหญ่เกินไปคุณจะแบ่งไฟล์ตามเนื้อหา)
Sridhar Sarnobat

1
@ Sridhar-Sarnobat โอ้คุณทำได้ ใช้ tee และ subshells เพื่อคัดลอก stdout ในหนึ่งคุณกรองในอื่น ๆ ย้อนกลับ การใช้ tee และ subshells แสดงให้เห็นใน usecase ที่ไม่เกี่ยวข้องแสดงให้เห็นที่นี่: blog.g3rt.nl/ …
gertvdijk

15

เพื่อทดสอบในเทอร์มินัลเท่านั้นใช้:

sed '/[cr]at/d' file_name

หากต้องการลบบรรทัดเหล่านั้นออกจากไฟล์ให้ใช้:

sed -i '/[cr]at/d' file_name


0

พิจารณาถ้าคุณมีไฟล์ที่มีfile_nameและคุณต้องการค้นหาเมาส์ แต่ในเวลาเดียวกันไม่กี่แถวจากเมาส์มีคำอื่น ๆ เช่นcatและratและคุณไม่ต้องการที่จะเห็นผู้ที่อยู่ในการส่งออกของคุณดังนั้นวิธีหนึ่งที่จะทำก็คือ -

grep -r mouse file_name | grep -vE "(cat|rat)"

0

เปลือกแบบพกพา

ทำงานใน/bin/shซึ่งเป็นdashบน Ubuntu เช่นเดียวกับและksh bashอึดอัดเล็กน้อยที่คุณต้องเขียนหลายกรณีทดสอบสำหรับแต่ละคำในcaseงบ แต่พกพา ทำงานร่วมกับกรณีที่คำปรากฏอยู่คนเดียวในบรรทัดในจุดเริ่มต้นจุดสิ้นสุดของบรรทัดหรือตรงกลางของบรรทัดและละเว้นที่มันอาจเป็นส่วนหนึ่งของคำอื่น

#!/bin/sh
line_handler(){
   # $1 is line read, prints to stdout
    case "$1" in
        cat|cat\ *|*\ cat\ *|*\ cat) true;; # do nothing if cat or rat in line
        rat|rat\ *|*\ rat\ *|*\ rat) true;; 
        *) printf "%s\n" "$1"
    esac
}

readlines(){
    # $1 is input file, the rest is words we want to remove
    inputfile="$1"
    shift

    while IFS= read -r line;
    do
        line_handler "$line" "$@"
    done < "$inputfile"
    [ -n "$line" ] && line_handler "$line" 
}

readlines "$@"

และนี่คือวิธีการทำงาน:

$ cat input.txt                                                                                                                                                        
the big big fat cat
the cat who likes milk 
jumped over gray rat
concat 
this is catchy
rat
rational
irrational
$ ./dellines.sh input.txt                                                                                                                                              
concat 
this is catchy
rational
irrational
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.