$SHLVLเมื่อฉันอ่านคำถามของคุณความคิดแรกของฉันคือ จากนั้นฉันเห็นว่าคุณต้องการนับvimระดับ
นอกเหนือจากระดับเชลล์ วิธีง่ายๆในการทำเช่นนี้คือการกำหนดฟังก์ชั่นเชลล์:
vim() { ( ((SHLVL++)); command vim "$@");}
การดำเนินการนี้จะเพิ่มขึ้นโดยอัตโนมัติSHLVL
ในแต่ละครั้งที่คุณพิมพ์vimคำสั่ง คุณจะต้องทำสิ่งนี้กับตัวแปรแต่ละตัวvi/ vimที่คุณเคยใช้ เช่น,
vi() { ( ((SHLVL++)); command vi "$@");}
view() { ( ((SHLVL++)); command view "$@");}
วงเล็บด้านนอกสร้างSHLVL
เชลล์ย่อยดังนั้นการเปลี่ยนแปลงด้วยตนเองในค่าของจะไม่ทำให้เกิดสภาพแวดล้อมเชลล์ (พาเรนต์) ปัจจุบัน แน่นอนว่าcommandคำหลักอยู่ที่นั่นเพื่อป้องกันไม่ให้ฟังก์ชั่นเรียกตนเอง (ซึ่งจะส่งผลให้เกิดการวนซ้ำแบบวนซ้ำไม่สิ้นสุด) และแน่นอนคุณควรใส่คำจำกัดความเหล่านี้ลงใน.bashrcไฟล์การเริ่มต้นเชลล์ของคุณหรือ
มีความไร้ประสิทธิภาพเล็กน้อยในข้างต้น ในบางเชลล์ (ทุบตีเป็นหนึ่ง) ถ้าคุณพูด
( cmd 1 ; cmd 2 ; … ; cmd n )
โดยที่เป็นโปรแกรมภายนอกที่เรียกใช้งานได้ (เช่นไม่ใช่คำสั่งในตัว) เชลล์จะเก็บกระบวนการพิเศษไว้รอบ ๆ เพื่อรอให้ยุติ นี่คือ (arguably) ไม่จำเป็น ข้อดีและข้อเสียเป็นที่ถกเถียงกัน หากคุณไม่คิดที่จะผูกหน่วยความจำสักเล็กน้อยและสล็อตกระบวนการ (และการเห็นกระบวนการเชลล์มากกว่าที่คุณต้องการเมื่อคุณทำ) ให้ทำข้างบนและข้ามไปยังส่วนถัดไป เหมือนกันถ้าคุณใช้เปลือกหอยที่ไม่ทำให้กระบวนการพิเศษอยู่รอบตัว แต่ถ้าคุณต้องการหลีกเลี่ยงกระบวนการพิเศษสิ่งแรกที่ควรลองคือcmdncmdnps
vim() { ( ((SHLVL++)); exec vim "$@");}
execคำสั่งจะมีการป้องกันไม่ให้กระบวนการเปลือกพิเศษจากเอ้อระเหย
แต่ก็มี gotcha การจัดการของ shell SHLVLนั้นค่อนข้างใช้งานง่าย: เมื่อเชลล์เริ่มทำงานเชลล์จะตรวจสอบว่าSHLVLมีการตั้งค่าไว้หรือไม่ หากยังไม่ได้ตั้งค่า (หรือตั้งค่าเป็นอย่างอื่นที่ไม่ใช่ตัวเลข) เชลล์จะตั้งค่าเป็น 1 หากตั้งค่าไว้ (เป็นตัวเลข) เชลล์จะเพิ่ม 1 ลงไป
แต่ด้วยเหตุผลนี้ถ้าคุณบอกว่าexec shคุณSHLVLควรขึ้นไป แต่นั่นเป็นสิ่งที่ไม่พึงประสงค์เนื่องจากระดับกระสุนจริงของคุณไม่เพิ่มขึ้น เชลล์จัดการสิ่งนี้โดยการลบออกจาก SHLVL
เมื่อคุณexec:
$ echo "$SHLVL"
1
$ set | grep SHLVL
SHLVL=1
$ env | grep SHLVL
SHLVL=1
$ (env | grep SHLVL)
SHLVL=1
$ (env) | grep SHLVL
SHLVL=1
$ (exec env) | grep SHLVL
SHLVL=0
ดังนั้น
vim() { ( ((SHLVL++)); exec vim "$@");}
เป็นการล้าง มันเพิ่มขึ้นSHLVLเพียงเพื่อลดมันอีกครั้ง คุณอาจจะแค่พูดvimโดยไม่ได้รับประโยชน์จากฟังก์ชั่น
หมายเหตุ:
ตามStéphane Chazelas (ใครจะรู้ทุกอย่าง)กระสุนบางตัวนั้นฉลาดพอที่จะไม่ทำสิ่งนี้ถ้าexecมันอยู่ใน subshell
ในการแก้ไขปัญหานี้คุณต้องทำ
vim() { ( ((SHLVL+=2)); exec vim "$@");}
จากนั้นฉันเห็นว่าคุณต้องการนับvimระดับ
อิสระจากระดับเปลือก ทีนี้เคล็ดลับเดียวกันนี้ใช้ได้ผลดี (ด้วยการดัดแปลงเล็กน้อย):
vim() { ( ((SHLVL++, VILVL++)); export VILVL; exec vim "$@");}
(และอื่น ๆ สำหรับvi, viewฯลฯ ) exportจำเป็นเพราะVILVLไม่ได้กำหนดไว้เป็นตัวแปรสภาพแวดล้อมโดยค่าเริ่มต้น แต่ไม่จำเป็นต้องเป็นส่วนหนึ่งของฟังก์ชั่น คุณสามารถพูดexport VILVLเป็นคำสั่งแยกต่างหาก (ในของคุณ.bashrc) และตามที่กล่าวไว้ข้างต้นหากกระบวนการเปลือกพิเศษไม่เป็นปัญหาสำหรับคุณคุณสามารถทำได้command vimแทนexec vimและทิ้งไว้SHLVLคนเดียว:
vim() { ( ((VILVL++)); command vim "$@");}
ความชอบส่วนบุคคล:
คุณอาจต้องการที่จะเปลี่ยนชื่อเพื่อสิ่งที่ต้องการVILVL VIM_LEVELเมื่อฉันดู“ VILVL” ดวงตาของฉันเจ็บปวด พวกเขาไม่สามารถบอกได้ว่ามันเป็นการสะกดผิดของ "ไวนิล" หรือตัวเลขโรมันที่ผิดรูปแบบ
หากคุณใช้เชลล์ที่ไม่สนับสนุนSHLVL(เช่นขีดกลาง) คุณสามารถใช้มันเองตราบเท่าที่เชลล์ใช้ไฟล์เริ่มต้น แค่ทำอะไรที่ชอบ
if [ "$SHELL_LEVEL" = "" ]
then
SHELL_LEVEL=1
else
SHELL_LEVEL=$(expr "$SHELL_LEVEL" + 1)
fi
export SHELL_LEVEL
ใน.profileไฟล์ของคุณหรือที่เกี่ยวข้อง (คุณอาจไม่ควรใช้ชื่อSHLVLเพราะจะทำให้เกิดความสับสนวุ่นวายหากคุณเริ่มใช้เชลล์ที่รองรับSHLVL)
คำตอบอื่น ๆ ได้กล่าวถึงปัญหาของการฝังค่าตัวแปรสภาพแวดล้อมลงในเชลล์พรอมต์ของคุณดังนั้นฉันจะไม่ทำซ้ำโดยเฉพาะอย่างยิ่งคุณบอกว่าคุณรู้วิธีการทำแล้ว
$SHLVLตัวแปร (ดูแลโดยหลายเปลือกหอย) สิ่งที่คุณกำลังมองหา?