PS1[3]=$SECONDS
PS1='${PS1[!(PS1[1]=!1&(PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600))
]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]/60%60), ${PS1[3]})):${PS1[1
]#${PS1[3]%%*??}0}$((PS1[3]=(PS1[2]%60), ${PS1[3]})):${PS1[1
]#${PS1[3]%%*??}0}$((PS1[3]=(SECONDS), ${PS1[3]})):'$PS1
สิ่งนี้จัดการการจัดรูปแบบโดยการคำนวณ - ดังนั้นในขณะที่มันขยายหลาย ๆ ครั้งมันไม่ทำ subshells หรือไปป์ใด ๆ
มันเพียงแค่ถือว่า$PS1
เป็นอาร์เรย์และใช้ดัชนีที่สูงขึ้นในการจัดเก็บ / คำนวณใด ๆ / ทุกสถานะที่จำเป็นระหว่างการแจ้งให้ ไม่มีสถานะเชลล์อื่นใดที่ได้รับผลกระทบ
00:00:46:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:00:[mikeserv@desktop tmp]$
00:00:01:[mikeserv@desktop tmp]$
00:00:43:[mikeserv@desktop tmp]$ sleep 10
00:00:33:[mikeserv@desktop tmp]$ sleep 10
00:00:15:[mikeserv@desktop tmp]$
00:00:15:[mikeserv@desktop tmp]$
00:00:02:[mikeserv@desktop tmp]$
00:02:27:[mikeserv@desktop tmp]$
ฉันสามารถทำลายมันลงได้เล็กน้อย ...
ก่อนอื่นให้บันทึกค่าปัจจุบันของ$SECONDS
:
PS1[3]=$SECONDS
ถัดไปให้กำหนด$PS1[0]
ตนเองแบบเรียกซ้ำในลักษณะที่จะตั้งค่าที่ถูกต้องเสมอ$PS1[1-3]
ในขณะที่การอ้างอิงตนเองพร้อมกัน ในการรับส่วนนี้คุณจะต้องพิจารณาลำดับที่นิพจน์เชลล์ - คณิตศาสตร์ได้รับการประเมิน สิ่งที่สำคัญที่สุดเชลล์เชลล์คือคำสั่งสุดท้ายของธุรกิจเชลล์เชลล์ ก่อนอื่นเชลล์จะขยายค่า $
ด้วยวิธีนี้คุณสามารถอ้างอิงเก่าค่าสำหรับเปลือกตัวแปรในนิพจน์คณิตศาสตร์หลังจากที่กำหนดโดยใช้
นี่คือตัวอย่างง่ายๆก่อน:
x=10; echo "$(((x+=5)+$x+x))" "$x"
40 15
เชลล์จะประเมินข้อความนั้นโดยการแทนที่ค่าแรกของ$x
ทุก ๆ ที่ที่$
ใช้การอ้างอิงเครื่องหมายดอลลาร์และดังนั้นการแสดงออกจึงกลายเป็น:
(x+=5)+10+x
... จากนั้นเชลล์จะเพิ่ม 5 ให้กับมูลค่า$x
และหลังจากนั้นจะขยายนิพจน์ทั้งหมดไปx+10+x
ในขณะที่ยังคงรักษาเฉพาะค่าที่กำหนดจริงในตัวแปรอ้างอิงเท่านั้น ค่าที่ขยายได้ของนิพจน์ทางคณิตศาสตร์คือ 40 แต่ค่าสูงสุด$x
คือ 15
นั่นคือวิธีการที่$PS1
สมการส่วนใหญ่ทำงานได้ดียกเว้นว่าจะมีการขยาย / ประเมินผลทางคณิตศาสตร์ในระดับอาเรย์เพิ่มเติม
PS1='${PS1[!(PS1[1]=!1&(...))]#...}...'
ฉันไม่แน่ใจจริงๆว่าทำไมฉันถึงเลือกที่จะใช้ที่PS1[1]=!1
นั่น - ฉันคิดว่ามันอาจจะเป็นแค่ความสวยงามที่โง่เง่า - แต่สิ่งนี้กำหนดให้ 0 $PS1[1]
ในขณะที่ขยายเพื่อทดแทนพารามิเตอร์ ค่าของ bitwise AND สำหรับ 0 และสิ่งอื่น ๆ จะเป็น 0 เสมอ แต่มันจะไม่ลัดวงจรเหมือนบูลีน&&
ทำเมื่อค่าหลักซ้ายสุดคือ 0 ดังนั้นนิพจน์เชิงซ้อนจะได้รับการประเมินทุกครั้ง นั่นเป็นสิ่งสำคัญแน่นอนเพราะอีลิสซิแรกนั้นเป็นที่ที่ค่าเริ่มต้น$PS1[2,3]
ถูกตั้งค่า
อย่างไรก็ตาม$PS1[1]
มั่นใจได้ว่าที่นี่จะเป็น 0 แม้ว่าจะมีการเปลี่ยนแปลงโดยไม่แจ้งให้ทราบ ภายในวงเล็บมี ...
PS1[3]=(PS1[2]=$SECONDS-${PS1[3]})/3600
... $PS1[2]
ได้รับการกำหนดความแตกต่างของ$PS1[3]
และ$SECONDS
และ$PS1[3]
ได้รับการหารความฉลาดของค่านั้นและ 3600 ค่าทั้งหมดจะเริ่มต้นได้ที่นี่ และอื่น ๆ :
${PS1[1]#${PS1[3]%%*??}0}
... ถ้ามีอย่างน้อยสองหลักใน$PS1[3]
นั้นการขยายตัวภายในจะเป็นโมฆะและเพราะเรารู้ว่า$PS1[1]
เป็น 0 ดังนั้นถ้า$PS1[3]
สามารถถูกแทนที่ด้วยอะไรก็ได้ดังนั้นก็เป็น$PS1[1]
อย่างอื่นมันก็จะขยายไปตามมูลค่าของมัน ด้วยวิธีนี้เฉพาะค่าตัวเลขหลักเดียวสำหรับการ$PS1[3]
กำหนดซ้ำแต่ละครั้งจะขยายศูนย์นำหน้าและ$PS1[3]
ขยายตัวเองแบบโมดูโล 60 ทันทีหลังจากนั้นในขณะที่ได้รับมอบหมายพร้อมกันค่าที่น้อยกว่าต่อไปสำหรับแต่ละชั่วโมงนาทีวินาที
ล้างและทำซ้ำจนกว่าจะมีการทำซ้ำครั้งล่าสุดเมื่อ$PS1[3]
ถูกเขียนทับด้วยค่าปัจจุบัน$SECONDS
เพื่อที่จะสามารถเปรียบเทียบได้$SECONDS
อีกครั้งเมื่อมีการแจ้งให้วาดถัดไป