$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) ไม่จำเป็น ข้อดีและข้อเสียเป็นที่ถกเถียงกัน หากคุณไม่คิดที่จะผูกหน่วยความจำสักเล็กน้อยและสล็อตกระบวนการ (และการเห็นกระบวนการเชลล์มากกว่าที่คุณต้องการเมื่อคุณทำ) ให้ทำข้างบนและข้ามไปยังส่วนถัดไป เหมือนกันถ้าคุณใช้เปลือกหอยที่ไม่ทำให้กระบวนการพิเศษอยู่รอบตัว แต่ถ้าคุณต้องการหลีกเลี่ยงกระบวนการพิเศษสิ่งแรกที่ควรลองคือcmdn
cmdn
ps
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
ตัวแปร (ดูแลโดยหลายเปลือกหอย) สิ่งที่คุณกำลังมองหา?