ฉันมีไฟล์ชื่อ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
/^$/d
statement1;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
P
rints ไม่มีอะไรเพราะสำหรับแต่ละเหล่านั้นมันเป็นสแต็คอินพุทในช่องว่างรูปแบบบรรทัดต่อบรรทัดในb
ลูปฟาร์มปศุสัตว์sed
สแต็กทั้งหมดจะถูกd
ลบ - และเพื่อให้ 3 บรรทัดแรกถูกถอดออกจากเอาต์พุตในการปัดทิ้งหนึ่งครั้งsed
ถึง$
บรรทัดสุดท้ายของอินพุตและพยายามดึงเข้าไปในส่วนขยายN
มันจะกระทบ EOF และหยุดการประมวลผลทั้งหมด แต่ในเวลานั้นพื้นที่รูปแบบนั้นมีทุกบรรทัด14,20
- ไม่มีสิ่งใดที่ถูกP
rinted และไม่เคยเป็น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
คือ 'แก้ไขข้อความมาตรฐานและควรจะมีอยู่ในระบบที่ไม่ได้มี sed
GNU เดิมทีถูกออกแบบมาเป็นโปรแกรมแก้ไขข้อความ แต่มันก็เหมาะสมกับการเขียนสคริปต์
printf '%s\n' 1d '$d' w q | ed Element_query
1d
ลบบรรทัดแรกของไฟล์$d
(อ้างเพื่อให้เปลือกไม่คิดว่ามันเป็นตัวแปร) ลบบรรทัดสุดท้ายw
เขียนไฟล์และลาออกq
ใช้ที่นี่เพื่อจัดรูปแบบคำสั่งสำหรับ- แต่ละอันจะต้องตามด้วยการขึ้นบรรทัดใหม่ มีวิธีอื่นที่จะทำให้สำเร็จed
printf
ed
มีหลายวิธีในการลบบรรทัดนำหน้าและส่วนท้ายออกจากไฟล์
คุณสามารถใช้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 ที่ผ่านมาการเปลี่ยนแปลงของ-1
head
การใช้awk
:
< inputfile awk 'NR>1 {print r}; {r=$0}' > outputfile
< inputfile
: เปลี่ยนเส้นทางเนื้อหาของinputfile
ไปawk
ที่stdin
> outputfile
: เปลี่ยนเส้นทางเนื้อหาของawk
's stdout
ไปoutputfile
NR>1
: ดำเนินการกระทำต่อไปนี้เฉพาะในกรณีที่จำนวนของระเบียนที่กำลังดำเนินการมากกว่า 1{print r}
: พิมพ์เนื้อหาของตัวแปร r
{r=$0}
: กำหนดเนื้อหาของบันทึกที่กำลังดำเนินการกับตัวแปร r
ดังนั้นในการดำเนินการครั้งแรกของawk
สคริปต์บล็อกแรกของการกระทำที่ไม่ได้ดำเนินการในขณะที่บล็อกที่สองของการกระทำจะถูกดำเนินการและเนื้อหาของบันทึกที่ได้รับมอบหมายให้กับตัวแปรr
; ในการดำเนินการครั้งที่สองจะมีการดำเนินการบล็อกแรกของการดำเนินการและเนื้อหาของตัวแปรr
จะถูกพิมพ์ (เพื่อบันทึกก่อนหน้านี้จะถูกพิมพ์); สิ่งนี้มีผลกระทบของการพิมพ์แต่ละบรรทัดที่ประมวลผล แต่บรรทัดแรกและบรรทัดสุดท้าย
r
คุณพิมพ์บรรทัดแรกของการป้อนข้อมูลที่เก็บไว้ใน