grep บรรทัดแรกยาวที่สุด
grep -Em1 "^.{$(wc -L <file.txt)}\$" file.txt
คำสั่งนั้นอ่านยากผิดปกติโดยไม่มีการฝึกฝนเพราะมันผสมไวยากรณ์ของเชลล์และ regexp
สำหรับคำอธิบายฉันจะใช้รหัสเทียมแบบง่ายก่อน บรรทัดที่ขึ้นต้นด้วย##
อย่ารันในเชลล์
รหัสที่ใช้ง่ายนี้ใช้ชื่อไฟล์ F และทำให้การอ้างอิงและส่วนต่าง ๆ ของ regexps อ่านได้ง่าย
มันทำงานอย่างไร
คำสั่งมีสองส่วนคือgrep
- และการwc
ร้องขอ:
## grep "^.{$( wc -L F )}$" F
wc
ถูกนำมาใช้ในการขยายกระบวนการดังนั้นจึงมีการเรียกใช้ก่อน$( ... )
grep
มันจะคำนวณความยาวของเส้นที่ยาวที่สุด ไวยากรณ์การขยายเชลล์ผสมกับไวยากรณ์รูปแบบการแสดงออกปกติในทางที่สับสนดังนั้นฉันจะสลายการขยายกระบวนการ:
## wc -L F
42
## grep "^.{42}$" F
ที่นี่การขยายกระบวนการถูกแทนที่ด้วยค่าที่จะกลับมาสร้างgrep
commandline ที่ใช้ ตอนนี้เราสามารถอ่านนิพจน์ทั่วไปได้ง่ายขึ้น: มันจับคู่กันตั้งแต่เริ่มต้น ( ^
) ถึงท้าย ( $
) ของบรรทัด การแสดงออกระหว่างพวกเขาตรงกับตัวละครใด ๆ ยกเว้นการขึ้นบรรทัดใหม่ซ้ำแล้วซ้ำอีก 42 ครั้ง รวมกันนั่นคือบรรทัดที่ประกอบด้วยอักขระ 42 ตัว
ตอนนี้กลับไปที่คำสั่งเชลล์จริง: grep
ตัวเลือก-E
( --extended-regexp
) ช่วยให้ไม่สามารถหลบหนี{}
เพื่อความสะดวกในการอ่าน ตัวเลือก-m 1
( --max-count=1
) ทำให้หยุดหลังจากพบบรรทัดแรก <
ในwc
คำสั่งเขียนไฟล์เพื่อ stdin ของตนเพื่อป้องกันwc
จากการพิมพ์ชื่อไฟล์พร้อมกับความยาว
สายไหนยาวที่สุด?
ในการทำให้ตัวอย่างอ่านง่ายขึ้นเมื่อชื่อไฟล์เกิดขึ้นสองครั้งฉันจะใช้ตัวแปรf
สำหรับชื่อไฟล์ แต่ละ$f
ตัวอย่างสามารถถูกแทนที่ด้วยชื่อไฟล์
f="file.txt"
แสดงบรรทัดที่ยาวที่สุดแรก - บรรทัดแรกที่ยาวที่สุดเท่าที่ยาวที่สุด:
grep -E -m1 "^.{$(wc -L <"$f")}\$" "$f"
แสดงบรรทัดที่ยาวที่สุดทั้งหมด - ทุกบรรทัดที่มีความยาวเป็นบรรทัดที่ยาวที่สุด:
grep -E "^.{$(wc -L <"$f")}\$" "$f"
แสดงบรรทัดที่ยาวที่สุดสุดท้าย - บรรทัดสุดท้ายที่ยาวเท่ากับบรรทัดที่ยาวที่สุด:
tac "$f" | grep -E -m1 "^.{$(wc -L <"$f")}\$"
แสดงบรรทัดที่ยาวที่สุดเดียว - บรรทัดที่ยาวที่สุดยาวกว่าบรรทัดอื่นทั้งหมดหรือล้มเหลว:
[ $(grep -E "^.{$(wc -L <"$f")}\$" "$f" | wc -l) = 1 ] && grep -E "^.{$(wc -L <"$f")}\$" "$f"
(คำสั่งสุดท้ายนั้นไม่มีประสิทธิภาพมากกว่าคำสั่งอื่น ๆ เนื่องจากทำซ้ำคำสั่ง grep ที่สมบูรณ์มันควรจะถูกย่อยสลายอย่างชัดเจนเพื่อให้ผลลัพธ์ของwc
และบรรทัดที่เขียนโดยgrep
ถูกบันทึกลงในตัวแปร
โปรดทราบว่าบรรทัดที่ยาวที่สุดอาจเป็นบรรทัดทั้งหมด . สำหรับการบันทึกในตัวแปรเพียงสองบรรทัดแรกเท่านั้นที่จะถูกเก็บไว้)