สถานการณ์การแยกข้อความนี้เป็นไปได้ใน linux bash shell หรือไม่

สมมติว่าไฟล์ข้อความของฉันเป็นแบบนี้

Person1 : movie1
(ช่องว่างและแท็บ) : ภาพยนตร์ 2
(ช่องว่างและแท็บ) : ภาพยนตร์ 3
(ช่องว่างและแท็บ) : ภาพยนตร์ 4

ฉันต้องการค้นหาภาพยนตร์โดยเฉพาะนักแสดง แล้วนี่คือวิธีที่ฉันจะทำสิ่งนี้

ทำนักแสดงแมว grep | grep 'movie3'

นี่จะให้บรรทัดที่ 3 แก่ฉันซึ่งเป็นบรรทัดว่างที่ unitl movie3 ปรากฏขึ้น ดังนั้นหากฉันสามารถได้บรรทัดแรกก่อนบรรทัดนี้ซึ่งเป็นไปตามรูปแบบนี้

grep '^[^ \t].'(ไม่ได้ขึ้นต้นด้วยช่องว่าง)

จะต้องสอดคล้องกับชื่อนักแสดงในหนังเรื่องนี้ (ผมไม่สนใจหนังที่นั่น)

มีการรวมกันของ sed/grep/awk ซึ่งสามารถช่วยฉันทำในเชลล์ได้หรือไม่? ฉันหวังว่าคำถามจะชัดเจน


person Dude    schedule 29.06.2014    source แหล่งที่มา


คำตอบ (4)


บิล เมอร์เรย์ ‹- วันกราวด์ฮอก ‹- grep พร้อมโหมด Perl Magic

ค่อนข้างยุ่งยาก แต่คุณสามารถใช้สิ่งนี้:

grep -P "(?sm)^\S+[^:\r\n]*?(?=\s*:(?:(?!^\S).)*?Groundhog Day)" mymoviefile

ดูการสาธิต

  • -P เปิดใช้งานโหมด Perl
  • (?sm) เปิดตัวดัดแปลงสองโหมด:
  • s เปิดใช้งานโหมด DOTALL ช่วยให้จุดตรงกันข้ามเส้น
  • m เปิดโหมดหลายบรรทัด โดยอนุญาตให้ ^ และ $ ตรงกันในแต่ละบรรทัด
  • จุดยึด ^ ยืนยันว่าเราอยู่ที่จุดเริ่มต้นของบรรทัด
  • \S+ จับคู่อักขระที่ไม่ใช่ช่องว่างตั้งแต่หนึ่งตัวขึ้นไป
  • [^:\r\n]*? จับคู่ตัวอักษรที่ไม่ใช่โคลอนหรือขึ้นบรรทัดใหม่อย่างเกียจคร้าน สูงสุด ...
  • จุดที่ lookahead (?=\s*:(?:(?!^\S).)*?Groundhog Day) สามารถยืนยันได้โดยไม่ต้องใช้ตัวอักษรว่าสิ่งที่ตามมาคือ...
  • \s*: ช่องว่างเพิ่มเติมและเครื่องหมายโคลอน
  • จากนั้น (?:(?!^\S).)* มีอักขระเป็นศูนย์หรือมากกว่านั้นที่ไม่ใช่อักขระเว้นวรรคที่จุดเริ่มต้นของบรรทัด จับคู่อย่างเกียจคร้านจนถึง...
  • Groundhog Day ชื่อหนัง!

ข้อมูลอ้างอิง

person zx81    schedule 29.06.2014
comment
ฉันพยายามเรียกใช้ มันไม่ได้ผล. นี่คือข้อความแสดงข้อผิดพลาด grep: unrecognized character after (? หรือ (?-. ฉันกำลังพยายามแก้ไขจุดบกพร่อง แต่เนื่องจากมันซับซ้อนมาก และฉันไม่รู้ถึงครึ่งหนึ่งของสิ่งที่คุณใช้ที่นี่ ฉันคิดว่าฉันจะ ต้องการความช่วยเหลือเพิ่มเติมของคุณ :^D - person Dude; 29.06.2014
comment
เพิ่มการปรับแต่งและปรับแต่งลองดูสิ :) - person zx81; 29.06.2014
comment
ขอบคุณสำหรับความช่วยเหลือของคุณแต่มันไม่เหมาะกับคนใจเสาะอย่างแน่นอน - person Dude; 29.06.2014
comment
อธิบายเสร็จแล้ว.. ` ไม่เหมาะกับคนใจเสาะอย่างแน่นอน ` คุณพูดถูก มันยังห่างไกลจากความชัดเจน แต่ด้วยคำอธิบาย ฉันแน่ใจว่าคุณจะเข้าใจมันได้ มันทำงานได้หรือเปล่า? - person zx81; 29.06.2014
comment
ขอบคุณเพื่อน ดีใจที่ช่วยได้! :) - person zx81; 29.06.2014
comment
หลังจากคำอธิบายนั้น จริงๆ แล้วฉันเป็นหนี้ชื่อเสียงคุณ 50-60 เป็นอย่างน้อย! :) - person Dude; 29.06.2014
comment
ไม่หรอก มันเป็นความยินดีอย่างยิ่ง ยินดีอย่างยิ่ง! :) หากคุณต้องการช่วยเหลือฉัน (หรือคุณ) ไปเรียนรู้ regex เจ๋ง ๆ เพิ่มเติม! :) ตัวอย่างเช่น มีคำถามที่น่าสนใจสองสามข้อในบานหน้าต่างด้านขวาของโปรไฟล์ของฉัน คำถามที่พบบ่อยเกี่ยวกับ regex ก็ดีเช่นกัน จากนั้นคำตอบจากเทพเจ้า regex บางส่วนที่นี่ (คลิกที่ผู้ใช้อันดับต้น ๆ ตลอดกาลในแท็ก regex) หรือไซต์เช่น Regularexpressions.info และ reexegg... Regex เจ๋งเลยเพื่อน! :) - person zx81; 29.06.2014

ฉันจะทำมันด้วย awk ถ้าฉันเข้าใจปัญหาถูกต้อง:

 awk -F: -v s="$search" '$1~/\S/{p=$1}$2~s{print $1 FS $2}' file

ทดสอบด้วย movie 3:

kent$ cat f
Person1 : movie1
          : movie 2
          : movie 3
          : movie 4

ในไฟล์ด้านบนมีช่องว่าง/แท็บนำหน้า

kent$  awk -F: -v s="movie 3" '$1~/\S/{p=$1}$2~s{print p FS $2}' f
Person1 : movie 3
person Kent    schedule 29.06.2014
comment
ฉันสร้างไฟล์เหมือนกับไฟล์ของคุณ ไม่มีช่องว่างนำหน้าในบรรทัดที่มี person1: movie1 และฉันก็ทำตามคำสั่งที่คุณให้ฉันมา มันให้ไว้แค่นี้ (เริ่มบรรทัด):หนัง 3 - person Dude; 29.06.2014
comment
ฉันอยู่บนลินุกซ์ คาดว่าจะใช้งานได้ในกรณีที่คุณรันบน Mac? - person Dude; 29.06.2014
comment
@ เพื่อนฉันมีลินุกซ์เท่านั้น ฉันเดาว่าเพราะเวอร์ชันเพ่งพิศของคุณต่ำกว่าของฉัน คุณจึงสามารถลอง: awk ... '$1~/[^ \t]/{....}' - person Kent; 29.06.2014
comment
ใช่มันได้ผล หากคุณไม่ว่าอะไร โปรดอธิบาย regex สั้นๆ หน่อยได้ไหม - person Dude; 29.06.2014
comment
@Dude regex กำลังจับคู่สตริง ($1 คอลัมน์แรก) หากมีอักขระที่ไม่ว่างเปล่า ปัญหาเช่นนั้นเป็นเรื่องปกติสำหรับ awk grep ดีมาก แต่ที่นี่ไม่ใช่เครื่องมือที่เหมาะสมสำหรับมัน (ความคิดเห็นของฉัน) - person Kent; 29.06.2014

สิ่งนี้อาจใช้ได้ผลสำหรับคุณ (GNU sed):

sed -n '/^\S/h;/movie 3/{H;x;s/:.*:/:/p}' file

ใช้สวิตช์ -n เพื่อให้ grep เป็นธรรมชาติ บันทึกบุคคลนั้นไว้ในพื้นที่พักและเพิ่มภาพยนตร์ต่อท้าย จากนั้นลบข้อความที่ไม่ต้องการออกแล้วพิมพ์ออกมา

person potong    schedule 29.06.2014

สิ่งนี้ค่อนข้างคลุมเครือ แต่ทำงานให้เสร็จ:

awk '/^[^ ]/{p=0} /Person1/{p=1} p'

ตัวอย่าง:

ไฟล์อินพุต:

Person1 : movie1
    : movie 2
    : movie 3
    : movie 4
Person2 : movie 5
    : movie 6

การดำเนินการ:

awk '/^[^ ]/{p=0} /Person1/{p=1} p' file
Person1 : movie1
    : movie 2
    : movie 3
    : movie 4

awk '/^[^ ]/{p=0} /Person2/{p=1} p' file
Person2 : movie 5
    : movie 6

OBS: ในบรรทัดคำสั่ง เอาต์พุตจะถูกเยื้อง

คำอธิบาย:

  1. หากบรรทัดไม่ได้ขึ้นต้นด้วยช่องว่าง ให้ตั้งค่า p=0
  2. หากบรรทัดมี Person1 ให้ตั้งค่า p=1
  3. ถ้า p=1 ให้พิมพ์ (ส่วนนี้ไม่ชัดเจน)

สามารถทำได้ใน perl เช่นกัน:

perl -ne '/^\w+/ && {$p=0}; /Person1/ && {$p=1}; $p && {print}' 
person Tiago Lopo    schedule 29.06.2014