พิมพ์เส้นเลขคี่พิมพ์เส้นคู่


18

ฉันต้องการพิมพ์บรรทัดเลขคี่และเลขคู่จากไฟล์

ฉันพบเชลล์สคริปต์นี้ซึ่งใช้ประโยชน์จากเสียงสะท้อน

#!/bin/bash
# Write a shell script that, given a file name as the argument will write
# the even numbered line to a file with name evenfile and odd numbered lines
# in a text file called oddfile.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------

file=$1
counter=0

eout="evenfile.$$" # even file name
oout="oddfile.$$" # odd file name

if [ $# -eq 0 ]
then
    echo "$(basename $0) file"
    exit 1
fi

if [ ! -f $file ]
then
    echo "$file not a file"
    exit 2
fi

while read line
do
    # find out odd or even line number
    isEvenNo=$( expr $counter % 2 )

    if [ $isEvenNo -ne 0 ]
    then
        # even match
        echo $line >> $eout
    else
        # odd match
        echo $line >> $oout
    fi
    # increase counter by 1
    (( counter ++ ))
done < $file
echo "Even file - $eout"
echo "Odd file - $oout"

แต่ไม่มีวิธีการทำในบรรทัดเดียวใช่ไหม

ใช่ใช้ awkฉันอ่าน

เส้นคู่ - เลข:

awk 'NR % 2' filename

เส้นเลขคี่:

awk 'NR % 2 == 1' filename

แต่มันไม่ได้ผลสำหรับฉัน ทั้งคู่ผลิตเอาต์พุตเดียวกันตาม diff เมื่อเปรียบเทียบกับไฟล์ต้นฉบับทั้งคู่จะมีความยาวเท่ากันครึ่งหนึ่งและทั้งคู่จะมีเส้นเลขคี่ ฉันกำลังทำอะไรผิดหรือเปล่า?


6
คนแรกควรเป็นNR % 2 == 0อย่างอื่นมิเช่นนั้นจะเท่ากับคนที่สอง
enzotib

ดูเหมือนจะมีเอกสารหลายฉบับออนไลน์ (รวมถึงเอกสารนี้) ที่ปรากฏที่ด้านบนของการค้นหาที่ระบุว่า NR% 2 ให้หมายเลขที่เป็นเลขคู่ซึ่งไม่ถูกต้องจะทำให้คุณแปลกเพราะ 1% 2 = 1 = true, 2% 2 = 0 = false
deltaray

คำตอบ:


12

ตามที่คุณถาม“ ในบรรทัดเดียว”:

awk '{print>sprintf("%sfile.%d",NR%2?"odd":"even",PROCINFO["pid"])}' filename

โปรดทราบว่ารหัสส่วนใหญ่เกิดจากตัวเลือกชื่อไฟล์แฟนซีเอาท์พุทของคุณ มิฉะนั้นรหัสต่อไปนี้จะเพียงพอที่จะใส่บรรทัดคี่ใน“ บรรทัด -1” และคู่สายใน“ บรรทัด -0”:

awk '{print>"line-"NR%2}' filename

26

ฉันชอบที่จะเข้ากันได้กับ POSIX ทุกครั้งที่ทำได้ดังนั้นฉันคิดว่าฉันจะโพสต์วิธีการอื่น ๆ ฉันมักจะใช้สิ่งเหล่านี้เพื่อทำให้ข้อความยุ่งเหยิงก่อนxargsท่อ

พิมพ์เส้นคู่

sed -n 'n;p'

พิมพ์เส้นเลขคี่

sed -n 'p;n'

แม้ว่าฉันมักจะใช้awkมันเกินความจริงสำหรับงานประเภทนี้


14

ง่ายมาก:

 sed -n 2~2p filename

จะพิมพ์บรรทัดที่มีเลขคู่จากชื่อไฟล์

sed -n 1~2p filename

จะพิมพ์บรรทัดเลขคี่


1
+1 สำหรับการไม่ใช้ AWK จากภายนอก ไม่ใช่ POSIX sed แต่ก็ยังคงเป็นวิธีที่ดี
JM Becker

@ TechZilla ฉันไม่เข้าใจ "การใช้ AWK จากภายนอก" - awk เป็น POSIX เช่นกัน
jw013

3
@ jw013: ไม่มีอะไรผิดปกติโดยawkส่วนตัวแล้วฉันใช้บ่อยมาก ฉันไม่เคยพูดอะไรเกี่ยวกับ 'ไม่ POSIX' เกี่ยวกับawkฉันหมายถึงsedตัวเลือกคำตอบ โดยเฉพาะ~โอเปอเรเตอร์เป็นส่วนขยาย GNU ซึ่งยังคงเป็นที่ยอมรับสำหรับคนจำนวนมาก เกี่ยวกับ 'การใช้ AWK awk จากภายนอก, I personally believe using สำหรับงานง่าย ๆ นี้คือ overkill ดังนั้น +1 สำหรับการจบงานกับยูทิลิตี้มีน้ำหนักเบากว่าsed awk
JM Becker

1
มีคนช่วยอธิบายวิธีใช้งานโอเปอเรเตอร์ที่นี่ได้ไหม?
ผู้เรียนตลอดกาล

9

สำหรับเลขคู่ควรมีรหัส

awk 'NR%2==0' filename

& สำหรับตัวเลขคี่

awk 'NR%2==1' filename

1
อันนี้สมบูรณ์แบบ แม้จะใช้งานได้หากคุณต้องการรับแถวเพิ่มขึ้นทีละ 10 บอกว่าคุณจำเป็นต้องลดขนาดไฟล์ที่สั่งขนาด 1 ล้านลงเหลือ 100k นี่คือสิ่งที่ฉันต้องการ
เด็กซ์เตอร์

คุณจะพิมพ์คอลัมน์ที่มีเลขคู่ใน AWK ได้อย่างไร? gawk 'FS=",";NF%2==0' file.csvฉันไม่สามารถรับทำงานนี้
hhh

2

คุณสามารถทำได้ด้วยการsedเรียกใช้ครั้งเดียวโดยไม่จำเป็นต้องอ่านไฟล์สองครั้ง:

sed '$!n
w even
d' infile > odd

หรือหากคุณต้องการในหนึ่งบรรทัด:

sed -e '$!n' -e 'w even' -e d infile > odd

โปรดทราบว่าสิ่งเหล่านี้จะไม่ให้ผลลัพธ์ที่คาดหวังหากไฟล์มีเพียงหนึ่งบรรทัด (บรรทัดจะถูกwritten ไปevenแทนที่จะoddเป็นบรรทัดแรกที่nไม่ได้ดำเนินการ) เพื่อหลีกเลี่ยงปัญหานี้ให้เพิ่มเงื่อนไข:

sed -e '$!n' -e '1!{w even' -e 'd}' infile > odd

มันทำงานอย่างไร ? ดีก็ใช้สามsedคำสั่ง:
n- ถ้าไม่ได้อยู่ในบรรทัดสุดท้ายพิมพ์พื้นที่รูปแบบที่จะstdout(ซึ่งถูกเปลี่ยนเส้นทางไปยังแฟ้มodd) แทนที่ด้วยบรรทัดถัดไป (ดังนั้นตอนนี้ก็ประมวลผลสายแม้) และยังคงดำเนินการคำสั่งที่เหลือ
w- ผนวก พื้นที่รูปแบบไปยังไฟล์even
d- ลบพื้นที่รูปแบบปัจจุบันและรีสตาร์ทวงจร - ผลข้างเคียงของสิ่งนี้คือsedจะไม่มีการพิมพ์พื้นที่รูปแบบอัตโนมัติโดยที่ไม่สิ้นสุดสคริปต์

กล่าวอีกนัยหนึ่งnจะถูกดำเนินการในบรรทัดที่แปลกและwและdจะดำเนินการเฉพาะในสายคู่ sedไม่เคยได้รับการพิมพ์อัตโนมัติเว้นแต่อย่างที่ฉันบอกว่าการป้อนข้อมูลประกอบด้วยบรรทัดเดียว


คุณช่วยอธิบายได้อย่างละเอียดว่ามันทำงานอย่างไร?
ผู้เรียนตลอดกาล

ขอบคุณมาก don_crissti สำหรับความช่วยเหลือของคุณ ขอแสดงความนับถือขอบคุณ upvoted เช่นกัน
ผู้เรียนตลอดกาล

0

ลองสิ่งนี้:

awk '{if(NR%2){print $0 > "odd.file"}else{print $0 > "even.file"}}' filename

คุณแน่ใจเกี่ยวกับการแสดงผลหมายเลขระเบียนหรือไม่
จัดการ

ขอโทษที่ฉันแก้ไขมันเพื่อส่งออกทั้งบรรทัด
renma

0

ฉันไปด้วยperlเพราะฉันชอบperl:

perl -pe 'BEGIN{open($e,">even_lines");open($o,">odd_lines")} $. % 2 ?select $o:select $e;'

ใช้ความจริงที่-pพิมพ์โดยนัยเพื่อจำลองแบบวิธีการsedทำงาน - และเราใช้selectเพื่อเลือกไฟล์ที่จะจัดการซึ่งเขียน

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