ฉันมีไฟล์ชื่อElement_queryที่มีผลลัพธ์ของแบบสอบถาม:
SQL> select count (*) from element;
[Output of the query which I want to keep in my file]
SQL> spool off;
ฉันต้องการลบบรรทัดที่ 1 และบรรทัดสุดท้ายโดยใช้คำสั่งเชลล์
ฉันมีไฟล์ชื่อElement_queryที่มีผลลัพธ์ของแบบสอบถาม:
SQL> select count (*) from element;
[Output of the query which I want to keep in my file]
SQL> spool off;
ฉันต้องการลบบรรทัดที่ 1 และบรรทัดสุดท้ายโดยใช้คำสั่งเชลล์
คำตอบ:
ใช้ GNU sed:
sed -i '1d;$d' Element_query
มันทำงานอย่างไร :
-iตัวเลือกแก้ไขไฟล์ของตัวเอง คุณสามารถลบตัวเลือกนั้นและเปลี่ยนเส้นทางผลลัพธ์ไปยังไฟล์ใหม่หรือคำสั่งอื่นหากคุณต้องการ1dลบบรรทัดแรก ( 1เพื่อดำเนินการในบรรทัดแรกเท่านั้นdเพื่อลบ)$dลบบรรทัดสุดท้าย ( $เพื่อดำเนินการกับบรรทัดสุดท้ายเท่านั้นdเพื่อลบ)ไปเพิ่มเติม:
1,5dจะลบ 5 บรรทัดแรกSQL>ใช้คำสั่ง/^SQL> /d/^$/dstatement1;statement2;satement3;...) หรือโดยการระบุแยกต่างหากในบรรทัดคำสั่ง ( -e 'statement1' -e 'statement 2' ...)1,3dจะลบสามบรรทัดแรก) แต่มันยากขึ้นเล็กน้อยในตอนท้าย ขึ้นอยู่กับสิ่งที่คุณต้องการคุณควรใช้สิ่งนี้ดีกว่า: sed -i '/^SQL> /d' Element_queryเพื่อลบบรรทัดที่ขึ้นต้นด้วยSQL> ไม่ว่าจะอยู่ที่ไหนในไฟล์
sedหนึ่งซับ - ซึ่งจะทำงานสำหรับการปอกสายโดยพลการนับจากหัวและส่วนท้ายของไฟล์ที่ดีกว่าแม้ว่าตราบใดที่อินพุตเป็นไฟล์ปกติเป็นเพียงการจัดกลุ่มอินพุตเดียวในสองheadกระบวนการ - มันเป็น วิธีที่เร็วที่สุดในการทำเช่นนี้มักจะ
sed -i '1d' table-backup.sqlลบบรรทัดแรกของไฟล์ข้อความ sql
{ head -n[num] >/dev/null
head -n[num]
} <infile >outfile
ด้วยข้างต้นคุณสามารถระบุจำนวนบรรทัดแรกที่จะตัดออกจากส่วนหัวของเอาต์พุตที่มีheadคำสั่งแรกและจำนวนบรรทัดที่จะเขียนoutfileด้วยที่สอง โดยทั่วไปแล้วจะทำสิ่งนี้เร็วกว่าsed- โดยเฉพาะเมื่ออินพุตมีขนาดใหญ่ - แม้ว่าจะต้องการการเรียกใช้สองครั้ง ที่ไหนsedแน่นอนควรเป็นที่ต้องการ แต่เป็นในกรณีที่<infileเป็นไม่ปกติlseekableไฟล์ - เพราะนี้จะมักจะไม่ได้ทำงานตามที่ตั้งใจไว้ในกรณีที่ว่า แต่sedสามารถจัดการกับการปรับเปลี่ยนการส่งออกทั้งหมดในกระบวนการเดียวสคริปต์
ด้วย GNU headคุณสามารถใช้-รูปแบบเชิงลบ[num]ในคำสั่งที่สองได้เช่นกัน ในกรณีนี้คำสั่งต่อไปนี้จะตัดบรรทัดแรกและบรรทัดสุดท้ายจากอินพุต:
{ head -n1 >/dev/null
head -n-1
} <infile >outfile
sed:ตัวอย่างเช่นฉันกำลังอ่านอินพุต 20 บรรทัดและฉันต้องการตัด 3 ตัวแรกและ 7 ตัวสุดท้ายถ้าฉันตัดสินใจที่จะทำเช่นนั้นด้วย / sedฉันจะทำด้วยหางบัฟเฟอร์ ฉันจะรวมสามและเจ็ดเข้าด้วยกันเพื่อนับจำนวนสตริปสิบแล้วทำ:
seq 20 | sed -ne:n -e '3d;N;1,10bn' -eP\;D
นั่นคือตัวอย่างที่แยก 3 และ 7 บรรทัดแรกจากอินพุต แนวคิดคือคุณสามารถบัฟเฟอร์ได้หลายบรรทัดตามที่คุณต้องการตัดจากส่วนท้ายของอินพุตในพื้นที่รูปแบบบนสแต็ก แต่ใช้เพียงPบรรทัดแรกของบรรทัดเหล่านี้สำหรับทุกบรรทัดที่ดึงเข้าไป
1,10 sed Prints ไม่มีอะไรเพราะสำหรับแต่ละเหล่านั้นมันเป็นสแต็คอินพุทในช่องว่างรูปแบบบรรทัดต่อบรรทัดในbลูปฟาร์มปศุสัตว์sedสแต็กทั้งหมดจะถูกdลบ - และเพื่อให้ 3 บรรทัดแรกถูกถอดออกจากเอาต์พุตในการปัดทิ้งหนึ่งครั้งsedถึง$บรรทัดสุดท้ายของอินพุตและพยายามดึงเข้าไปในส่วนขยายNมันจะกระทบ EOF และหยุดการประมวลผลทั้งหมด แต่ในเวลานั้นพื้นที่รูปแบบนั้นมีทุกบรรทัด14,20- ไม่มีสิ่งใดที่ถูกPrinted และไม่เคยเป็นsed Pเรียกใช้เฉพาะ ewline แรกที่เกิดขึ้น\nในพื้นที่รูปแบบเท่านั้นและจะDลบเหมือนเดิมก่อนที่จะเริ่มรอบใหม่ด้วยสิ่งที่เหลืออยู่ - หรืออินพุต 6 บรรทัดถัดไป บรรทัดที่ 7 ถูกต่อท้ายอีกครั้งกับสแต็กด้วยNคำสั่ง ext ในรอบใหม่และเพื่อให้การseqของเอาท์พุท(ซึ่งเป็น 20 หมายเลขตามลำดับเส้น) , sedเพียงพิมพ์:
4
5
6
7
8
9
10
11
12
13
สิ่งนี้จะเป็นปัญหาเมื่อจำนวนบรรทัดที่คุณต้องการตัดออกจากส่วนท้ายของอินพุตมีขนาดใหญ่เนื่องจากsedประสิทธิภาพของมันจะแปรผันตรงกับขนาดของพื้นที่รูปแบบ แต่ถึงกระนั้นมันก็เป็นทางออกที่ทำงานได้ในหลายกรณี - และ POSIX ระบุsedพื้นที่รูปแบบที่จะจัดการอย่างน้อย 4kb ก่อนที่จะหยุด
tailยังรองรับtail -n+<num>ความหมายของไวยากรณ์เพิ่มเติม"เริ่มจากบรรทัด<num>"
ฉันจะไม่ตอบวิธีลบจำนวนบรรทัด ฉันจะโจมตีปัญหาด้วยวิธีนี้:
grep -v '#SQL>' Element_query >outfile
แทนที่จะนับบรรทัดมันจะกำจัดคำสั่ง SQL ด้วยการจดจำพร้อมต์ วิธีแก้ปัญหานี้สามารถทำให้เป็นมาตรฐานสำหรับไฟล์เอาต์พุตอื่นของเซสชัน SQL ที่มีคำสั่งมากกว่าสองไฟล์
edคือ 'แก้ไขข้อความมาตรฐานและควรจะมีอยู่ในระบบที่ไม่ได้มี sedGNU เดิมทีถูกออกแบบมาเป็นโปรแกรมแก้ไขข้อความ แต่มันก็เหมาะสมกับการเขียนสคริปต์
printf '%s\n' 1d '$d' w q | ed Element_query
1dลบบรรทัดแรกของไฟล์$d(อ้างเพื่อให้เปลือกไม่คิดว่ามันเป็นตัวแปร) ลบบรรทัดสุดท้ายwเขียนไฟล์และลาออกq ใช้ที่นี่เพื่อจัดรูปแบบคำสั่งสำหรับ- แต่ละอันจะต้องตามด้วยการขึ้นบรรทัดใหม่ มีวิธีอื่นที่จะทำให้สำเร็จedprintfed
มีหลายวิธีในการลบบรรทัดนำหน้าและส่วนท้ายออกจากไฟล์
คุณสามารถใช้awkเนื่องจากมันรองรับทั้งการจับคู่รูปแบบและการนับบรรทัด
#you need to know length to skip last line, assume we have 100 lines
awk 'NR>1 && NR<100 {print $0};' < inputfile
#or
awk '/SQL/ {next}; {print $0;};' < inputfile |awk 'NR>1&& NR<10 {print $0};'
คุณสามารถใช้grep -vเพื่อแยกบรรทัดที่คุณไม่ต้องการตามรูปแบบและคุณสามารถจับคู่หลายรูปแบบโดยใช้-Eตัวเลือก
grep -v -E "SQL>" < inputfile > outputfile
คุณสามารถใช้headและtailตัดจำนวนเส้นที่ระบุ
lines=$((`wc -l < inputfile`-2)) #how many lines in file, less 2
head -n-1 < inputfile | head -n$lines > outputfile
#or
tail -n+2 < inputfile | head -n$lines > outputfile
คุณสามารถใช้vi/vimและลบบรรทัดแรกและบรรทัดสุดท้ายได้
vi inputfile
:1
dd
:$
dd
:w! outputfile
:x
คุณสามารถใช้สคริปต์ Perl ข้ามบรรทัดแรกบันทึกแต่ละบรรทัดพิมพ์เมื่อคุณได้รับบรรทัดถัดไป
#left as exercise for the reader :-)
headที่คุณไม่จำเป็นต้องใช้ในท่อและในความเป็นจริงมันจะดีกว่าที่จะไม่ใช้เลยถ้าคุณสามารถหนีไปได้ เมื่อคุณทำhead | head- ในขณะที่กระบวนการทั้งสองสามารถทำงานพร้อมกันพวกเขาทั้งสองก็กำลังประมวลผลข้อมูลเดียวกันทั้งหมดในทางปฏิบัติซ้ำซ้อน ถ้าคุณทำแทน{ head >dump; head >save; } <inคุณจะข้ามโดยชดเชย - ครั้งแรกที่อ่าน 10 บรรทัดออกไป>dumpและครั้งที่สองอ่านต่อไป 10 >saveเส้นออกไป
คุณจะได้รับบริการที่ดียิ่งขึ้นโดยการตัดคำสั่ง SQL ออกไป คุณสามารถทำได้สองวิธี:
ถ้าคุณแน่ใจอย่างแน่นอนว่าลำดับ " SQL>" จะไม่เกิดขึ้นที่ใดก็ตามในเอาต์พุต
grep -v -F 'SQL> ' < infile > outfileหากคุณไม่แน่ใจ
grep -v '^SQL> .*;$' < infile > outfileรุ่นที่สองช้ากว่า แต่มีความแม่นยำมากกว่า: จะละเว้นบรรทัดที่ขึ้นต้นด้วย "SQL>" และลงท้ายด้วยเครื่องหมายอัฒภาคซึ่งดูเหมือนจะอธิบายบรรทัดที่คุณต้องการตัดออก
อย่างไรก็ตามจะเป็นการดีกว่าถ้าไม่ให้ใส่เอาต์พุตพิเศษนั้นในไฟล์เพื่อเริ่มต้น ระบบ SQL ส่วนใหญ่มีวิธีการทำเช่นนั้น ฉันไม่ได้คุ้นเคยกับ Oracle มากนัก แต่คำตอบนี้อาจมีประโยชน์
คุณสามารถเลือกบรรทัดระหว่างช่วงawk(สมมติว่าคุณรู้ว่ามีกี่บรรทัด):
awk 'NR>1 && NR < 3' file
หรือในภาษา Perl:
perl -ne 'print if $.>1 && $.<3' file
หากคุณไม่ทราบว่ามีกี่บรรทัดคุณสามารถคำนวณได้ทันทีโดยใช้grep(โปรดทราบว่านี่จะไม่นับบรรทัดว่างให้ใช้grep -c '' fileเพื่อนับพวกเขาเช่นกัน):
awk -vm="$(grep -c . file2.txt)" 'NR>1 && NR<m' file2.txt
ลองวิธีนี้:
tail -n +2 name_of_file | head -n-1
การปรับแต่ง
คุณสามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อลบ n บรรทัดแรกที่เปลี่ยน+2ของtail;
หรือลบเส้น n ที่ผ่านมาการเปลี่ยนแปลงของ-1head
การใช้awk:
< inputfile awk 'NR>1 {print r}; {r=$0}' > outputfile
< inputfile: เปลี่ยนเส้นทางเนื้อหาของinputfileไปawkที่stdin> outputfile: เปลี่ยนเส้นทางเนื้อหาของawk's stdoutไปoutputfileNR>1: ดำเนินการกระทำต่อไปนี้เฉพาะในกรณีที่จำนวนของระเบียนที่กำลังดำเนินการมากกว่า 1{print r}: พิมพ์เนื้อหาของตัวแปร r{r=$0}: กำหนดเนื้อหาของบันทึกที่กำลังดำเนินการกับตัวแปร rดังนั้นในการดำเนินการครั้งแรกของawkสคริปต์บล็อกแรกของการกระทำที่ไม่ได้ดำเนินการในขณะที่บล็อกที่สองของการกระทำจะถูกดำเนินการและเนื้อหาของบันทึกที่ได้รับมอบหมายให้กับตัวแปรr; ในการดำเนินการครั้งที่สองจะมีการดำเนินการบล็อกแรกของการดำเนินการและเนื้อหาของตัวแปรrจะถูกพิมพ์ (เพื่อบันทึกก่อนหน้านี้จะถูกพิมพ์); สิ่งนี้มีผลกระทบของการพิมพ์แต่ละบรรทัดที่ประมวลผล แต่บรรทัดแรกและบรรทัดสุดท้าย
rคุณพิมพ์บรรทัดแรกของการป้อนข้อมูลที่เก็บไว้ใน