ฉันจะไพพ์แต่ละคำสั่งที่กำหนดให้กับเชลล์ได้อย่างไร?


14

ฉันต้องการแก้ไข. bashrc ของฉันเพื่อให้ทุกคำสั่งที่ดำเนินการบนเชลล์นั้นถูกไพพ์ไปที่บางอย่างเช่น:

 $ sudo apt update
  _________________
< sudo apt update >
 -----------------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

ฉันจัดการสิ่งที่ค่อนข้างคล้ายกัน แต่ไม่ใช่ทั้งหมด:

$ bash
$ exec > >(cowsay)
$ echo "Hello AU!"
$ exit
 _______
< Hello AU! >
 -------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

ไม่ใช่ผลลัพธ์ที่ต้องการเนื่องจากเกิดขึ้นหลังจากออกจากเชลล์ปัจจุบันเท่านั้น

มันมีวัตถุประสงค์เพื่อความสนุก / การเรียนรู้เป็นหลัก


การใช้-nแฟล็กถึงcowsayมีประโยชน์ มันทำให้มันรักษาช่องว่าง
wjandrea

คำตอบ:


12

คุณสามารถปรับวิธีการของคุณได้เล็กน้อย แทนการไพพ์ไปที่cowsayโดยตรงอ่านเอาต์พุตจนกว่าอักขระที่คั่น, ส่งเอาต์พุตนั้นไปยังcowsayจากนั้นพิมพ์อักขระนั้นหลังจากทุกคำสั่ง:

exec > >(while IFS= read -d '' -r line; do if [[ -n $line ]]; then echo; printf "%s\n" "$line" | cowsay; fi; done)
PROMPT_COMMAND='printf "\0"'

ที่นี่ฉันใช้อักขระ ASCII NUL คุณสามารถใช้อย่างอื่นที่ไม่น่าจะปรากฏในเอาท์พุทคำสั่ง

สิ่งนี้จะพิมพ์หลังจากพรอมต์ดังนั้นผลลัพธ์จะน่าเกลียด:

$ export LC_ALL=C
$ exec > >(while IFS= read -d '' -r line; do if [[ -n $line ]]; then echo; printf "%s\n" "$line" | cowsay; fi; done)
$ PROMPT_COMMAND='printf "\0"'
$ ls
$
 ______________________________________
/ Desktop Documents Downloads Music    \
| Pictures Public Templates Videos
\ examples.desktop                     /
 --------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

$ echo foo
$
 ______
< foo  >
 ------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

โปรดทราบว่าสิ่งนี้จะทำลายคำสั่งใด ๆ ที่พยายามใช้งานเอาต์พุตที่ซับซ้อนหรือมีส่วนต่อประสานกับผู้ใช้ข้อความ (คิดว่าตัวแก้ไขบรรทัดคำสั่งเพจเจอร์ ฯลฯ )

สมมติว่าคุณรู้อยู่แล้วว่าสิ่งexec > >(...)ใดมีส่วนในกระบวนการทดแทนคือ:

  • while IFS= read -d '' -r line; do ... done: นี่เป็นสำนวนที่พบบ่อยพอสมควรสำหรับการอ่านข้อมูลที่คั่นด้วยอักขระ ASCII NUL:

    • IFS= ตั้งค่า IFS เป็นสตริงว่างซึ่งปิดใช้งานการแยกฟิลด์
    • -rป้องกันreadจากการปฏิบัติ\ในการป้อนข้อมูลเป็นพิเศษ ( \nเช่นเช่นอ่าน\nและไม่แปลงเป็นอักขระขึ้นบรรทัดใหม่)
    • -d ''เป็นวิธีที่จะบอกreadให้อ่านจนกระทั่งอักขระ NUL

    ดังนั้นสิ่งทั้งหมดจึงวนซ้ำไปยังอินพุตในส่วนที่คั่นด้วย NUL ในขณะที่รักษาเนื้อหาของอินพุตให้มากที่สุด

  • if [[ -n $line ]]; then ... fi; done - ทำเฉพาะเมื่ออินพุตที่อ่านจนถึงตอนนี้ไม่ว่างเปล่า
  • echo; printf "%s\n" "$line" | cowsay;- พิมพ์บรรทัดว่างนำหน้าเพื่อให้เอาต์พุต cowsay ไม่ขัดแย้งกับพรอมต์จากนั้นส่งอินพุตที่อ่านจนถึง cowsay มีความน่าเชื่อถือมากขึ้นและปลอดภัยกว่าprintfecho

1
เมื่อพรอมต์ของฉันมีการหยุดแบบ linebreak ภายในเอาต์พุต cowsay จะปะทะกับส่วนที่สองของมัน - อาจตั้งค่าพรอมต์ให้เป็นบางสิ่งที่ไม่ทำให้เสียสมาธิ
ของหวาน

16

คุณสามารถtrapและใช้DEBUGสัญญาณของ bash ในทางที่ผิด:

trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG

ตัวอย่างการวิ่ง

$ trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG
$ echo "AU is awesome!"
 __________________
< AU is awesome! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
AU is awesome!

อย่างไรก็ตามสิ่งนี้จะยังคงรันคำสั่งหลังจากนั้น ขอบคุณilkkachuฉันพบวิธีแก้ไข:

$ shopt -s extdebug
$ trap 'bash -c "$BASH_COMMAND" | cowsay; false' DEBUG
$ echo "AU is awesome!"
 __________________
< AU is awesome! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.