บอกว่าคำสั่งสุดท้ายว่างเปล่าใน PROMPT_COMMAND


12

ในทุบตีจากภายใน PROMPT_COMMAND มีวิธีที่จะบอกว่าผู้ใช้เพียงกด 'กลับ' และไม่ได้ป้อนคำสั่งหรือไม่?

คำตอบ:


7

ตรวจสอบว่าหมายเลขประวัติเพิ่มขึ้นหรือไม่ พรอมต์ที่ถูกยกเลิกหรือพรอมต์ที่ผู้ใช้เพิ่งกดEnterจะไม่เพิ่มหมายเลขประวัติ

หมายเลขประวัติพร้อมใช้งานในตัวแปรHISTCMDแต่ไม่สามารถใช้ได้ในPROMPT_COMMAND(เพราะสิ่งที่คุณต้องการในความเป็นจริงหมายเลขประวัติของคำสั่งก่อนหน้าคำสั่งที่เรียกใช้PROMPT_COMMANDตัวเองไม่มีหมายเลขประวัติ) fcคุณจะได้รับตัวเลขจากการส่งออกของ

prompt_command () {
  HISTCMD_previous=$(fc -l -1); HISTCMD_previous=${HISTCMD_previous%%$'[\t ]'*}
  if [[ -z $HISTCMD_before_last ]]; then
    # initial prompt
  elif [[ $HISTCMD_before_last = "$HISTCMD_previous" ]]; then
    # cancelled prompt
  else
    # a command was run
  fi
  HISTCMD_before_last=$HISTCMD_previous
}
PROMPT_COMMAND='prompt_command'

โปรดทราบว่าหากคุณเปิดใช้การบีบอัดรายการที่ซ้ำกันในประวัติศาสตร์ ( HISTCONTROL=ignoredupsหรือHISTCONTROL=erasedups) สิ่งนี้จะรายงานคำสั่งที่ว่างเปล่าโดยไม่ตั้งใจหลังจากเรียกใช้คำสั่งที่เหมือนกันสองคำติดต่อกันอย่างต่อเนื่อง


ขอบคุณ Gilles ฉันพลาดอะไรบางอย่างที่นี่ ดูเหมือนว่าจะไม่ทำงานเนื่องจากการวาง 'echo hello' ในบรรทัดแรกของฟังก์ชันตัวอักษรไม่ทำงานแม้ว่า PROMPT_COMMAND = 'echo hello' ฉันคิดว่าอาจเป็นปัญหาของ HISTCMD_prepre เทียบกับ HISTCMD_PREVIOUS แต่ไม่มีลูกเต๋า ฉันจะแสดงความเห็นต่อไป แต่ฉันแสดงความคิดเห็นเนื่องจาก bash fu ของคุณชัดเจนกว่าลีกของฉัน
ผู้ใช้

@user ฉันแก้ไขข้อผิดพลาดเพิ่มเติมโดยเฉพาะอย่างยิ่ง${HISTCMD_previous%%$'[\t ]'*}บิตหายไป$'…'และสิ้นสุดการตัดทอนหลังจาก`, t` หรือเว้นวรรคแทนแท็บหรือเว้นวรรคหลัง แต่ทุบตีพิมพ์แท็บ
Gilles 'หยุดความชั่วร้าย'

1
วิธีการแก้ปัญหานี้ขึ้นอยู่กับข้อสันนิษฐานที่ซ้ำกันจะถูกบันทึกไว้ในประวัติศาสตร์ (ซึ่งปิดสำหรับฉัน) ดังนั้นโซลูชันนี้จะไม่ทำงานตามที่คาดไว้สำหรับคำสั่งที่ทำซ้ำในขณะที่รายการที่ซ้ำกันจะไม่ถูกบันทึกในประวัติ
schlimmchen

4

มีวิธีแก้ปัญหา แต่มีข้อกำหนดบางประการ:

คุณต้องตั้งค่า$HISTCONTROLให้บันทึกคำสั่งทั้งหมดรวมทั้งทำซ้ำและเว้นวรรค ดังนั้นตั้ง:

HISTCONTROL=

ตอนนี้กำหนดฟังก์ชั่นการโทรเป็น$PROMPT_COMMAND:

isnewline () {
  # read the last history number
  prompt_command__isnewline__last="$prompt_command__isnewline__curr"
  # get the current history number
  prompt_command__isnewline__curr="$(history 1 | grep -oP '^\ +\K[0-9]+')"
  [ "$prompt_command__isnewline__curr" = "$prompt_command__isnewline__last" ] && \
    echo "User hit return"
}

ตอนนี้ตั้งค่า$PROMPT_COMMANDตัวแปร:

PROMPT_COMMAND="isnewline"

ดูผลลัพธ์:

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 

ฉันไม่เข้าใจว่าทำไมคุณถึงใช้ไฟล์ชั่วคราวที่นี่ ตัวแปรlastจะถูกเก็บรักษาไว้ตั้งแต่การเรียกisnewlineใช้ครั้งถัดไปจนถึงถัดไป (เลือกชื่อสามัญที่น้อยกว่าprompt_command__isnewline__lastเพื่อหลีกเลี่ยงการปะทะกัน)
Gilles 'หยุดความชั่วร้าย'

@Gilles คุณกำลังขวาผมเปลี่ยนมันขอบคุณสำหรับคำแนะนำของคุณ
ความวุ่นวาย

ขอบคุณความวุ่นวาย ฉันใช้แนวคิดเดียวกันสำหรับสิ่งต่อไปนี้ซึ่งง่ายกว่าในการแยกวิเคราะห์ HISTCONTROL="" function last_was_blank { local last_command="$(history 1)" if [[ "$last_was_blank_PREVIOUS_LINE" = "$last_command" ]] ; then echo "true" else echo "false" fi export last_was_blank_PREVIOUS_LINE="$last_command" } PROMPT_COMMAND=last_was_blank
ผู้ใช้

1

ผมไม่ทราบวิธีที่จะทำอย่างนั้นต่อ se แต่คุณสามารถได้รับผลกระทบเดียวกันโดยใช้

ดักจับดีบักsome_command_or_function

สิ่งนี้จะทำให้การsome_command_or_functionถูกเรียกเมื่อใดก็ตามที่คุณเรียกใช้คำสั่ง สิ่งที่ยุ่งยากคือมันจะไม่ถูกเรียกถ้าคุณเพิ่งกดEnter- เว้นแต่ว่าคุณได้กำหนด PROMPT_COMMAND ไว้ในกรณีนี้การกดปุ่มEnterจะเรียกใช้ PROMPT_COMMAND ซึ่งในทางกลับกันจะทำให้เกิดกับดัก

บางทีวิธีที่ง่ายที่สุดในการบรรลุผลลัพธ์ที่คุณต้องการคือการกำหนดฟังก์ชั่นการตรวจแก้จุดบกพร่องแทนการใช้ PROMPT_COMMAND แต่ฉันบอกไม่ได้เพราะฉันไม่รู้ว่าคุณต้องการผลอะไร หากคุณต้องการสิ่งที่จะเกิดขึ้นเมื่อคุณกดEnterและสิ่งที่แตกต่าง / เพิ่มเติมเกิดขึ้นเมื่อคุณพิมพ์คำสั่งแล้ว (AFAIK) คุณต้องใช้กับดักจับการดีบักและ PROMPT_COMMAND ดูคำตอบนี้และอัน  นี้ เพื่อหาวิธีที่จะทำให้กลไกทั้งสองเล่นร่วมกันได้ดี


0

(ซึ่งจะได้รับความคิดเห็นที่ได้รับการยอมรับคำตอบถ้าผมได้รับอนุญาตให้เพิ่มความคิดเห็น ... ) @schlimmen คุณอาจตั้งHISTTIMEFORMATเพื่อสิ่งที่ต้องการแล้วบันทึกและเปรียบเทียบHISTTIMEFORMAT='%F %T ' history 1เป็นเพราะการลบอย่างน้อยเวลาประทับของคำสั่งสุดท้าย (อาจจะซ้ำ) การเปลี่ยนแปลงทุกครั้ง --- และด้วยการHISSTIMEFORMATตั้งค่าอย่างเหมาะสมhistory 1จะแสดงการประทับเวลา (ไม่เหมือนfc) และทำให้แตกต่างกันระหว่างคำสั่งซ้ำ

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