ใช้ตัวแปรเพื่อจัดเก็บรหัสสีของเทอร์มินัลสำหรับ PS1 หรือไม่


33

ในของ.bashrcฉันฉันใช้รหัสสีเทอร์มินัล ANSI เพื่อ colorize บิตต่าง ๆ ดูเหมือนว่านี้:

PS1='\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ '

ที่ไหนvirtual_envและgit_branchฟังก์ชั่นทุบตีสิ่งที่ส่งออกใน stdout

ตอนนี้เพื่อให้ง่ายต่อการอ่านและแก้ไข, PS1ฉันต้องการที่จะเก็บรหัสสีในตัวแปรและหมายถึงพวกเขาแทนการฝังพวกเขาโดยตรงใน ดังนั้นฉันจึงมีตัวแปรหลายอย่างเช่นนี้:

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[0m\]"

ฉันต้องการที่จะสามารถเขียนสิ่งที่ชอบ:

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

แต่วิธีนี้ใช้ไม่ได้ - รหัสสีจะแสดงขึ้นมาในพรอมต์ราวกับว่ามันกำลังหลบหนี สีที่ทำงานอย่างถูกต้องถ้าผมใช้คำพูดสองแทนแต่แล้วก็พรอมต์เพียงการเปลี่ยนแปลงเมื่อฉันทำPS1source ~/.bashrc

ฉันได้พยายามสิ่งอื่น ๆ ที่ผมเคยเห็นคนทำ - การใช้printfและไม่ใช้คำพูดเดียวสำหรับสีวาง\[และ\]ในPS1แทนของตัวแปรสี แต่ไม่มีอะไรน่าจะทำงาน

ฉันจะใช้ตัวแปรสำหรับรหัสสีได้อย่างไร


คุณสามารถให้เราของคุณ.bashrc?
cuonglm

@cuonglm. bashrc ทั้งหมดของคุณเป็นของเราหรือไม่ ฉันจะแสดงตัวเองออกมา
CivFan

คำตอบ:


20

วิธีแก้ไขคือให้เชลล์แทนที่ตัวแปรสีเมื่อกำหนดพรอมต์ แต่ไม่ใช่ฟังก์ชั่น หากต้องการทำสิ่งนี้ให้ใช้เครื่องหมายคำพูดคู่ที่คุณเคยลอง แต่หนีออกจากคำสั่งเพื่อไม่ให้มีการประเมินจนกว่าจะมีพรอมต์คำสั่งปรากฏขึ้น

PS1="\u@\h:\w${YELLOW}\$(virtual_env)${GREEN}\$(git_branch)${RESET}$ "

แจ้งให้ทราบล่วงหน้า\ก่อนที่$()ในแต่ละคำสั่ง

ถ้าเราสะท้อนสิ่งนี้เราจะเห็นว่า:

echo "$PS1"
\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ 

อย่างที่คุณเห็นตัวแปรสีได้ถูกแทนที่ แต่ไม่ใช่คำสั่ง


1
สิ่งนี้ดูเหมือนจะไม่ทำงานหาก $ (git_branch) กำลังพยายามพิมพ์โดยใช้ $ {YELLOW} เป็นต้นในส่วนนั้นเพียงอย่างเดียวคุณจะยังได้รับอักขระ [] ทั้งหมด
WB Reed

7

ปัญหาคือตัวแปรของคุณGREENมีสตริงตัวอักษรที่ประกอบด้วย "backslash bracket backslash zero สามสาม" เป็นต้น มันไม่มีตัวอย่างเช่นอักขระ ASCII escape ตามที่ต้องการเพื่อให้เทอร์มินัลของคุณเปลี่ยนสี

คุณสามารถใส่เข้าไปในตัวควบคุมGREEN(และYELLOWและRESET) ด้วยตนเอง แต่เป็นตัวเลือกที่ดีมากคือการใช้tputในสถานที่แรกเพื่อที่คุณจะไม่จำเป็นต้องยากรหัสอะไรและคุณจะให้การสนับสนุนประเภทอาคารใด ๆ

GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput setaf 0)"

เหตุผลที่ทำให้โลกเกิดขึ้นเมื่อคุณใส่ "backslash zero three สาม" ฯลฯ ... โดยตรงลงในPS1นั้นคือการตีความลำดับ backslash บางอย่างเป็นคุณลักษณะของการพร้อมท์ของ bash (ดูที่ส่วน PROMPTING ในคู่มือการทดแทนนี้เกิดขึ้นก่อนการขยายพารามิเตอร์ แม้ว่าการทดแทนการขยายตัวทางคณิตศาสตร์และการลบเครื่องหมายคำพูดดังนั้นจึงไม่ได้นำไปใช้กับผลลัพธ์ของการดำเนินการอื่น ๆ ทั้งหมด


5
เมื่อทำมันด้วยวิธีนี้คุณจะต้องห่อตัวแปรสีในภายใน\[\] $PS1ตัวอย่างเช่นPS1='\u@\h:\w\[${YELLOW}\]'. หากคุณไม่ทำเช่นนี้และจบลงด้วยคำสั่งยาวที่ล้อมรอบบรรทัดถัดไปคุณจะพบกับปัญหาทุกประเภท เชลล์ใช้\[\]เพื่อกำหนดว่าอักขระใดที่ไม่สามารถพิมพ์ได้ดังนั้นจึงไม่รวมถึงการคำนวณความยาวพรอมต์ มันต้องการสิ่งนี้เพื่อให้สามารถวาดเส้นได้อย่างถูกต้องเมื่อเกินความกว้างของเทอร์มินัล
Patrick

ฉันไม่รู้เรื่องtputขอบคุณ ฉันจะใช้คำตอบของ Patrick ตอนนี้ แต่ฉันจะทบทวนสิ่งนี้เมื่อฉันมีโอกาส
Ismail Badawi

2

เปลี่ยนวิธีการเติม $ GREEN $ YELLOW และ $ RESET:

GREEN="$(echo -e "\033[32m")"
YELLOW="$(echo -e "\033[33m")"
RESET="$(echo -e "\033[0m")"

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

1
สิ่งนี้มีผลเช่นเดียวกันกับคำตอบของ Celada แต่ Celada's สามารถพกพาได้มากกว่าในกรณีที่เครื่องใช้รหัสหลบหนีที่แตกต่างกันสำหรับการตั้งค่าสี มันจะมีปัญหาเดียวกันกับสิ่งต่าง ๆ ที่มีหลายบรรทัด
Patrick

2
\[…\]บิตต้องการที่จะยังคงอยู่ในการแจ้งคุณไม่สามารถยัดในตัวแปร คุณได้ลบมันออกไปโดยสิ้นเชิงซึ่งจะส่งผลให้เกิดปัญหาในการแสดงผล (เคอร์เซอร์ไม่อยู่ในตำแหน่งที่ทุบตีคาดว่าจะได้)
Gilles 'หยุดชั่วร้าย'

นอกเหนือจาก @Patrick เกี่ยวกับ echo -e ไม่สามารถพกพาได้
helpermethod

1
ด้วยคุณสมบัติที่ไม่สะดวกในการพกพาtput setafทำให้คุณไม่ต้องเลือกชุดสี "แสง" เช่นสีฟ้าอ่อน อย่างไรก็ตามคำตอบของ Cyrus
CivFan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.