เหตุใด $ anchor สุดท้ายของบรรทัดจึงไม่ทำงานกับคำสั่ง grep ถึงแม้ว่า front-of-line ^ anchor จะเป็นอย่างไร


19

ใหม่มากสำหรับ UNIX แต่ไม่ใหม่สำหรับการเขียนโปรแกรม การใช้ Terminal บน MacBook เพื่อวัตถุประสงค์ในการจัดการและค้นหารายการคำสำหรับการสร้างคำไขว้ฉันพยายามใช้ประโยชน์จากคำสั่ง Grep และรูปแบบที่หลากหลาย ดูเหมือนจะตรงไปตรงมา แต่การวางสายก่อนกับสิ่งที่ฉันคิดว่าควรเป็นกรณีที่ง่าย

เมื่อฉันเข้า

grep "^COW" masternospaces.txt

ฉันได้สิ่งที่ต้องการ: รายการคำทั้งหมดที่เริ่มต้นด้วย COW

แต่เมื่อฉันเข้า

grep "COW$" masternospaces.txt

ฉันคาดหวังว่าจะได้รับรายการคำที่ลงท้ายด้วย COW (มีคำพูดมากมาย) และไม่มีอะไรคืนเลย

ไฟล์เป็นไฟล์ข้อความธรรมดาโดยมีทุกบรรทัดเพียงแค่คำ (หรือวลีคำศัพท์ที่ไม่มีช่องว่าง) ในตัวพิมพ์ใหญ่ทั้งหมด

มีความคิดอะไรที่จะเกิดขึ้นที่นี่?


3
ต้นกำเนิดของไฟล์ masternospaces.txt คืออะไร เป็นไปได้หรือไม่ที่จะมีการยกเลิกบรรทัดสไตล์ Windows (CR-LF) แทนที่จะเป็น LF แบบ Unix
ขับขี่เหล็ก

2
ไม่แน่ใจ แต่ที่คุณกำลังมองหารายการคำหรือรายการของสาย ... ?
mikeserv

steeldriver - สิ่งที่เป็นความคิดแรกของฉัน ไม่แน่ใจว่าจะตรวจสอบสิ่งที่เกิดขึ้นที่นั่นหรือสิ่งที่เป็นไปได้ สมมติว่าการคืนปลายทางเป็นการสิ้นสุดการส่งคืน ไฟล์นั้นเป็นบทสรุปที่ยิ่งใหญ่จากแหล่งข้อมูลไม่กี่แห่ง ฉันไม่แน่ใจด้วยซ้ำว่าไฟล์ตัวใดที่จะถือว่าเป็นไฟล์ต้นฉบับ และผ่านการใช้โปรแกรมประมวลผลคำอย่างน้อยสามตัวบนเครื่อง PC และ Mac อะไรจะเป็นวิธีที่ดีที่สุดในการดูว่ามีการใช้การยุติประเภทใด
DTalvacchio

mikeserv-- ในไฟล์. txt นี้ทุกบรรทัดเป็นเพียงคำ (หรือวลีที่ไม่มีช่องว่างระหว่างคำดังนั้นจึงเป็น "คำ" อีกครั้ง ดังนั้นฉันกำลังค้นหาบรรทัดฉันคิดว่า . . เพียงว่าแต่ละบรรทัดมีเพียงหนึ่งในสิ่งที่ฉันกำลังพิจารณาคำสำหรับวัตถุประสงค์ไขว้
DTalvacchio

1
คุณสามารถใช้hexdumpเพื่อตรวจสอบวิธีการจัดรูปแบบการสิ้นสุดบรรทัดของคุณ ฉันแนะนำให้คุณใช้รูปแบบที่ฉันชอบ: hexdump -e '"%08_ad (0x%08_ax) "8/1 "%02x "" "8/1 "%02x "' -e '" "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt. กับการส่งออกให้ตรวจสอบปลายสาย: 0a-> LF, ->0d CR
user43791

คำตอบ:


23

ดังที่ @steeldriver ถูกกล่าวถึงปัญหาน่าจะเกิดจากรูปแบบการสิ้นสุดบรรทัดที่แตกต่างจากที่grepคาดไว้

เพื่อตรวจสอบปลายสาย

คุณสามารถใช้hexdumpเพื่อตรวจสอบวิธีการจัดรูปแบบการสิ้นสุดบรรทัดของคุณ ฉันแนะนำให้คุณใช้รูปแบบที่ชื่นชอบ:

hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt

กับการส่งออกให้ตรวจสอบปลายสาย: 0a-> LF, ->0d CRตัวอย่างรวดเร็วมากจะให้อะไรเช่นนี้

$ hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt
00000000 (0x00000000)    4e 6f 20 43 4f 57 20 65   6e 64 69 6e 67 0d 0a 45    No COW e|nding..E
00000016 (0x00000010)    6e 64 69 6e 67 20 69 6e   20 43 4f 57 0d 0a          nding in| COW..

0d 0aหมายเหตุปลายสายในรูปแบบดอส:

หากต้องการเปลี่ยนการสิ้นสุดบรรทัด

คุณสามารถดูที่นี่หรือที่นี่สำหรับวิธีการต่าง ๆ ของการเปลี่ยนจุดสิ้นสุดบรรทัดโดยใช้เครื่องมือต่าง ๆ แต่สำหรับสิ่งเดียวคุณสามารถใช้ vi / vim:

vim masternospaces.txt
:set fileformat=unix
:wq

เพื่อ grep โดยไม่ต้องเปลี่ยนอะไร

หากคุณต้องการgrepจับคู่ไม่ว่าจุดสิ้นสุดของบรรทัดจะเป็นอย่างไรคุณสามารถระบุการสิ้นสุดของบรรทัดดังนี้:

grep 'COW[[:cntrl:]]*$' masternospaces.txt

หากบรรทัดว่างปรากฏขึ้นคุณสามารถตรวจสอบว่าคุณได้จับคู่บางสิ่งบางอย่างโดยใช้-vตัวเลือกcat:

grep 'COW[[:cntrl:]]*$' masternospaces.txt | cat -v

ฉันชอบส่วนตัว

คุณสามารถทำได้ทั้ง grep และสร้างมาตรฐานผลลัพธ์โดยใช้sed:

sed -n '/COW^M*$/{;s/^M//g;p;};' masternospaces.txt

ที่^Mได้มาจากการพิมพ์Ctrl-V Ctrl-Mบนแป้นพิมพ์

หวังว่านี่จะช่วยได้!


นั่นคือทั้งหมดที่เป็นประโยชน์อย่างมาก ฉันหมดเวลาในวันนี้ แต่จะมองผ่านสิ่งเหล่านี้อย่างใกล้ชิดในวันพรุ่งนี้และดูว่ามีอะไร หากในขณะเดียวกันคุณคนใดมีลิงค์ไปยังคู่มืออ้างอิงคำสั่ง Unix ที่คุณชื่นชอบเพื่อที่ฉันจะได้สอนตัวเองเล็กน้อยเกี่ยวกับการทำงานของสิ่งต่าง ๆ ฉันจะขอบคุณมัน ฉันได้รับชิ้นส่วนที่นี่และที่นั่น แต่ยังไม่พบแหล่งที่มาที่ฉันไปสำหรับคำอธิบาย ขอบคุณทุกคนและจะเช็คอินในวันพรุ่งนี้ด้วยการอัปเดตที่ประสบความสำเร็จอย่างหวังว่า --D
DTalvacchio

มันแย่มากที่โพสต์นี้ปิดไม่ได้สำหรับฉันอย่างน้อย สำหรับชีวิตของฉันฉันไม่สามารถหาวิธีจับคู่ส่วนท้ายของบรรทัดได้ หากฉันถ่ายโอนฐานสิบหกฉันไม่พบบรรทัดที่ดีที่ลงท้ายด้วยตัวอย่างของคุณด้านบน ฉันไม่คุ้นเคยกับการทำงานกับฐานสิบหกดังนั้นฉันจึงอาจอ่านมันไม่ถูกต้อง ฉันได้ลองใช้[[:cntrl:]]@ user43791 แนะนำแล้วและมันก็ยังไม่ตรงกับสิ่งใดสำหรับฉัน มันไม่สมเหตุสมผล ฉันใช้ GNU grep 2.20 และแยกเอาท์พุทจาก nDPI ซึ่งเขียนไปยังแฟ้มข้อความ
harperville

@harperville หากcat -v yourfile.extคุณเห็นอะไร
user43791

ดีไม่มีอะไรจะตื่นเต้นหรือคาดไม่ถึง แค่เนื้อหาเท่าที่ฉันคาดหวังที่จะเห็นพวกเขา มีอะไรพิเศษที่คุณกำลังมองหาใช่ไหม ฉันไม่สามารถวางผลลัพธ์ที่นี่ แต่ฉันเพิ่งเห็นเนื้อหา OL ปกติ' ASCII ภาษาอังกฤษข้อความ file"ตาม
harperville

@harperville ไม่มีส่วนเสริม "^ M" ในตอนท้ายของแต่ละบรรทัดหรือไม่ คุณสามารถวาง hex สองสามบรรทัดแรกได้ไหม
user43791

1

แม้ว่าคุณสามารถใช้ไวยากรณ์ 'มาตรฐาน' RegEx กับ grep (ตามคำตอบของ @ user43791 ), grep ยังมีตัวระบุอื่น ๆ เพื่อแสดงขอบเขตอินพุต

ผู้จับคู่สำหรับการเริ่มต้นและสิ้นสุดของทั้งบรรทัดคือ\`(backtick) (แทน^) และ\'(apostrophe) (แทน$ )

ดังนั้นสำหรับคำสั่งดั้งเดิมของคุณคุณจะใช้: grep "COW\'" masternospaces.txt

หมายเหตุด้านข้าง: มันเป็นสิ่งสำคัญที่จะต้องทราบว่า?และ+จะได้รับการปฏิบัติอย่างแท้จริงเว้นแต่คุณจะหลบหนีพวกเขาโดยใช้\?และ\+เพื่อให้พวกเขาเป็นคู่หูเลือกสไตล์ RegEx

ที่มา: grepไวยากรณ์นิพจน์ปกติ


grep ใช้เวลา ^ (caret) เพื่อเริ่มและ \ '(apostrophe) สิ้นสุด
GypsyCosmonaut

1

อีกวิธีในการลบ\rgrep ก่อนหน้า:

... | dos2unix | egrep 'COW$' | ...

ฉันชอบที่มันชัดเจนมากเพราะฉันจำอะไรไม่ได้[[:cntrl:]]นาน


-2

"COW $" เมื่อ bash ตั้ง pararameter สำหรับ grep มันถูกตีความว่าเป็น 'COW' โดยที่ถือว่า "$" เป็น "" เนื่องจาก $ เป็น simbol escape เมื่อไม่มีสิ่งใดที่ $ เป็นเพื่อนมันถูกตีความว่าเป็นสตริงว่างโดยเปลือก bash ดังนั้นคุณควรใช้ grep 'COW $' masternospaces.txt แทน


3
เนื่องจากไม่มีการขยายที่ถูกต้องของ$มันจะถูกทิ้งไว้โดยลำพังและใช้ grep ดูตัวเอง: echo "COW$"- $จะยังคงอยู่ที่นั่น
Jeff Schaller

-3

ใน grep BSD คุณต้องหลบหนี "$" และใส่สตริงของคุณในเครื่องหมายคำพูดคู่:

"COW\$"

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