โดยทั่วไปแล้วฉันมักจะมองหาการsed
ประมวลผลข้อความ - โดยเฉพาะอย่างยิ่งสำหรับไฟล์ขนาดใหญ่ - และมักจะหลีกเลี่ยงการทำสิ่งต่าง ๆ เหล่านั้นในเชลล์เอง
แต่ฉันคิดว่ามันอาจเปลี่ยนไป ฉันแหย่ไปรอบ ๆman ksh
และฉันสังเกตเห็นสิ่งนี้:
<#pattern Seeks forward to the beginning of the
next line containing pattern.
<##pattern The same as <# except that the por‐
tion of the file that is skipped is
copied to standard output.
ฉันสงสัยว่ามันมีประโยชน์ในโลกแห่งความเป็นจริงฉันจึงลองทำดู ฉันทำ:
seq -s'foo bar
' 1000000 >file
... สำหรับข้อมูลนับล้านเส้นที่มีลักษณะดังนี้:
1foo bar
...
999999foo bar
1000000
... และรับมือกับมันsed
เช่น:
p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"
do </tmp/file eval "time ( $c )"
done | wc -l
ดังนั้นทั้งสองคำสั่งควรมีแถบสูงสุด999999fooและการใช้รูปแบบการจับคู่ของพวกเขาต้องประเมินอย่างน้อยที่สุดจุดเริ่มต้นและจุดสิ้นสุดของแต่ละบรรทัดเพื่อที่จะทำเช่นนั้น พวกเขายังต้องตรวจสอบถ่านแรกกับรูปแบบเมื่อตะกี้ นี่เป็นสิ่งที่ง่าย แต่ ... ผลลัพธ์ไม่ใช่สิ่งที่ฉันคาดไว้:
( sed '/^[^0-8]99999.*bar/q' ) \
0.40s user 0.01s system 99% cpu 0.419 total
( ksh -c ':<##@(~(E)^[^0-8]99999.*bar)' ) \
0.02s user 0.01s system 91% cpu 0.033 total
1999997
ksh
ใช้ ERE ที่นี่และsed
BRE ฉันทำสิ่งเดียวกันกับksh
และรูปแบบของเชลล์มาก่อน แต่ผลลัพธ์ไม่ได้แตกต่างกัน
อย่างไรก็ตามนั่นเป็นความแตกต่างที่มีนัยสำคัญ - มีksh
ประสิทธิภาพมากกว่าsed
10 เท่า ฉันเคยอ่านมาก่อนแล้วว่า David Korn เขียน io lib ของเขาเองและนำไปใช้ksh
- อาจจะเกี่ยวข้องหรือไม่ - แต่ฉันไม่รู้อะไรเลย เปลือกมันทำยังไงดี?
สิ่งที่น่าประหลาดใจสำหรับฉันยิ่งกว่าก็คือksh
มันปล่อยให้มันถูกต้องตรงจุดที่คุณถาม ที่จะได้รับ(เกือบ)ออกเดียวกันของ(GNU) sed
คุณต้องใช้-u
- ช้ามาก
นี่คือการทดสอบgrep
v ksh
:
1000000 #grep + head
( grep -qm1 '^[^0-8]99999.*bar'; head -n1; ) \
0.02s user 0.00s system 90% cpu 0.026 total
999999foo bar #ksh + head
( ksh -c ':<#@(~(E)^[^0-8]99999.*bar)'; head -n1; ) \
0.02s user 0.00s system 73% cpu 0.023 total
ksh
เต้นgrep
ที่นี่ - แต่มันก็ไม่เสมอไป - มันผูกกันแน่นทีเดียว ถึงกระนั้นมันก็ค่อนข้างดีและ ksh
ให้head
อินพุตของlookahead ก่อนเริ่มการแข่งขัน
ฉันคิดว่ามันดีเกินกว่าจะเป็นจริงได้ คำสั่งเหล่านี้ทำอะไรที่แตกต่างกันภายใต้ประทุน?
โอ้และเห็นได้ชัดว่าไม่มีแม้แต่ subshell ที่นี่:
ksh -c 'printf %.5s "${<file;}"'
pattern
แสดงออกปกติหรือรูปแบบเปลือกง่ายขึ้น?