ยกเว้นอักขระที่ไม่ใช่การพิมพ์ในฟังก์ชันสำหรับพรอมต์ Bash


22

ใน Bash Prompt (ตัวแปร PS1) ฉันกำลังเรียกใช้ฟังก์ชันเพื่อเพิ่มข้อความลงในพรอมต์: export PS1="\u@\h \$(my_function) \$ "

อย่างไรก็ตามฟังก์ชั่นในพรอมต์ประกอบด้วยรหัสสี ANSI ที่เปลี่ยนไปตามเอาท์พุทของฟังก์ชั่น (บางครั้งสีแดงบางครั้งก็เป็นสีเขียว) เพิ่ม " \[" เพื่อตัวแปร PS1 ควรหลบหนีรหัสเหล่านั้นเป็นที่พิมพ์ไม่ แต่ถ้าผมทำechoในฟังก์ชั่นที่ " \[" ได้รับการพิมพ์ตัวอักษรในการแจ้ง

ฉันจะหลีกเลี่ยงรหัสสี ANSI เหล่านี้จากภายในฟังก์ชั่นเพื่อใช้ในพรอมต์ทุบตีได้อย่างไร

คำตอบ:


34

ReadLineห้องสมุดยอมรับ\001และ\002(ASCII SOH และ STX ) เป็นตัวคั่นข้อความที่ไม่พิมพ์ เหล่านี้ยังทำงานในโปรแกรมใด ๆ ที่ใช้readLine

จากlib/readline/display.c:243ในซอร์สโค้ดของbash :

243 /* Current implementation:
244         \001 (^A) start non-visible characters
245         \002 (^B) end non-visible characters
246    all characters except \001 and \002 (following a \001) are copied to
247    the returned string; all characters except those between \001 and
248    \002 are assumed to be `visible'. */

ทุบตี -specific \[และ\]ในความเป็นจริงการแปลเป็น\001และที่\002y.tab.c:7640


หมายเหตุ: ถ้าคุณใช้bash 's printfหรือecho -eถ้าข้อความของคุณมี\001หรือ\002อยู่ก่อนหมายเลขคุณจะพบกับbug ของbashที่ทำให้ตัวเลขนั้นกินหนึ่งหลักมากเกินไปเมื่อประมวลผล escal octal - นั่นคือ\00142จะถูกตีความว่าเป็นฐานแปด 014 (ตามด้วย ASCII "2") แทนเลขฐานแปดที่ถูกต้อง 01 (ตามด้วย ASCII "42") ด้วยเหตุนี้ใช้รุ่นเลขฐานสิบหก\x01และ\x02แทน


นั่นมัน! echo -e "\001\e[31m\002RED"ทำงานตามที่คาดไว้ ขอบคุณ!
เที่ยงคืน

ขออภัยที่จะฟื้นคำตอบอีกครั้ง แต่สิ่งที่เทียบเท่ากับ dash / ash / sh?
Hosh Sadiq

@Hosh หากพวกเขาใช้ readline \001และ\002จะใช้งานได้ มิฉะนั้นฉันไม่แน่ใจ ขีดกลางตัวอย่างไม่ใช้ readlineแน่นอน
wjandrea

1

นี่คือคำตอบที่สมบูรณ์ดี ฉันต้องขุดมากขึ้นเพื่อหาว่า \ 001 ฯลฯ ต้องไปที่ไหน หวังว่านี่จะช่วยได้

# Color prompt for git
reset=$(tput sgr0)
boldgreen=$(tput setaf 2)$(tput bold)
cyan=$(tput sgr0)$(tput setaf 6)
boldred=$(tput setaf 1)$(tput bold)
boldwhite=$(tput setaf 7)$(tput bold)
boldyellow=$(tput setaf 3)$(tput bold)

PARENCLR=$'\001\e[0;36m\002'
BRANCHCLR=$'\001\e[1;33m\002'

alias branchname="git branch 2>/dev/null | grep '*' | sed 's/* \(.*\)/ ${PARENCLR}(${BRANCHCLR}\1${PARENCLR}\)/'"

GIT_STATUS='$(branchname)'

PROMPT_CHAR="\$"
PS1="\[$boldgreen\]\u\[$cyan\]::\[$boldred\]\h \[$cyan\]{\[$boldwhite\].../\W\[$cyan\]}\[$reset\]$GIT_STATUS\[$reset\]$PROMPT_CHAR "

วิธีที่ฉันตั้งค่าไว้ที่นี่วงเล็บสาขาคอมไพล์จะปรากฏเฉพาะเมื่อคุณอยู่ในสาขาคอมไพล์มิฉะนั้นจะว่างเปล่า


0

ตามคำตอบของ grawityต่อไปนี้จะใส่ลำดับการควบคุม ANSI ใน ASCII SOH( ^A) และSTX( ^B) ซึ่งเทียบเท่า\[และ\]ตามลำดับ:

function readline_ANSI_escape() {
  if [[ $# -ge 1 ]]; then
    echo "$*"
  else
    cat  # Read string from STDIN
  fi | \
  perl -pe 's/(?:(?<!\x1)|(?<!\\\[))(\x1b\[[0-9;]*[mG])(?!\x2|\\\])/\x1\1\x2/g'
}

ใช้มันเหมือน:

$ echo $'\e[0;1;31mRED' | readline_ANSI_escape

หรือ:

$ readline_ANSI_escape "$string"

เป็นโบนัสการใช้งานฟังก์ชั่นหลาย ๆ ครั้งจะไม่หนีรหัสควบคุมอีกครั้ง


-2

\[ถ้าคุณต้องการที่จะใช้พวกเขาในการแจ้งแล้วคุณต้องทำ \033[แต่ถ้าคุณต้องการที่จะใช้ในเสียงสะท้อนที่คุณต้องใช้


อืม ... การเพิ่ม \ 033 [ก่อนคำสั่ง ANSI ("\ e [31m") และ \ 033] หลังจากดูเหมือนว่าจะทำให้ตัวอักษรที่พิมพ์ถัดไปในพรอมต์ไม่พิมพ์
เที่ยงคืน

1
คุณไม่ต้องการทำ \ 033] หลังจากนั้น \ 033 [31m เริ่มสีหลังจากนั้นคุณจำเป็นต้องตั้งค่ากลับด้วย \ 033 [0m
Wuffers
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.