กด space เพื่อดำเนินการต่อ


73

ฉันจะหยุดสคริปต์ทุบตีจนกว่าผู้ใช้จะกดได้Spaceอย่างไร

ฉันต้องการมีคำถามในสคริปต์ของฉัน

กด space เพื่อดำเนินการต่อหรือCTRL+ Cเพื่อออก

จากนั้นสคริปต์ควรหยุดและรอจนกว่าจะกด Space


ทั้งหมดนี้และอื่น ๆ ได้รับการแก้ไขใน SO Q&A BTW นี้: ลินุกซ์เทียบเท่ากับ DOS หยุดชั่วคราวคืออะไร?
slm


คำตอบ:


58

คุณสามารถใช้read:

read -n1 -r -p "Press space to continue..." key

if [ "$key" = '' ]; then
    # Space pressed, do something
    # echo [$key] is empty when SPACE is pressed # uncomment to trace
else
    # Anything else pressed, do whatever else.
    # echo [$key] not empty
fi

12
คุณควรเพิ่ม -s เพื่อไม่พิมพ์อักขระที่กดลงบนเทอร์มินัล และเพิ่ม linebreak ในตอนท้ายมิฉะนั้นผลลัพธ์จะดำเนินต่อไปโดยตรงในบรรทัดเดียวกันเช่นคำถาม ดีที่สุดคือ:read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
rubo77

1
สคริปต์นี้ไม่ทำงาน เพิ่งทดสอบบน Red Hat linux ... elseบล็อกจะทำงานอยู่เสมอแม้ว่าจะกด spacebar ก็ตาม
เบิร์ต

3
@ Robert bashมันเป็นเพราะคุณไม่ได้ใช้ มันทำงานได้ถ้าคุณใช้แทนถ้าคุณมีบางเปลือกอื่นที่ไม่ใช่read _ bash
Niklas Rosencrantz

ควร''มีช่องว่างภายในหรือไม่
Jose Antonio Dura Olmos

นี่เป็น''สตริงว่าง ไม่มีพื้นที่ภายใน ฉันเดาว่ามันพอดีถ้าคุณป้อน ENTER หรือ TAB
rubo77

44

วิธีการที่กล่าวถึงในคำถามและคำตอบ SO นี้น่าจะเป็นตัวเลือกที่ดีที่สุดสำหรับทางเลือกในpauseพฤติกรรมที่คุณคุ้นเคยกับการใช้งาน Windows เมื่อทำไฟล์ BAT

$ read -rsp $'Press any key to continue...\n' -n1 key

ตัวอย่าง

ที่นี่ฉันกำลังเรียกใช้ข้างต้นแล้วเพียงแค่กดปุ่มใด ๆ ในกรณีนี้Dกุญแจ

$ read -rsp $'Press any key to continue...\n' -n1 key
Press any key to continue...
$ 

อ้างอิง


ผมหมายถึงว่าทำไม$ก่อนสตริงในที่นี่: -rsp $'Press?
rubo77

2
@ rubo77 - อา นั่นเป็นวิธีที่คุณสามารถทำสตริงตัวอักษรที่มีอักขระพิเศษ เป็นรูปแบบ: $ '... '
slm

1
@ rubo77 - มันแตกต่างกัน นั่นคือเครื่องหมายดอลลาร์พร้อมคำพูดสองเท่าฉันใช้คำพูดดอลลาร์พร้อมคำพูดเดียว โปรดลบความคิดเห็นนั้นผิด
slm

1
อ่าฉันเข้าใจ ในกรณีที่คุณใส่ลำดับหนีในพรอมต์สตริง ดูwiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
rubo77

@ rubo77 - ใช่สัญลักษณ์นั้นอนุญาตให้มีการรวมลำดับการยกเว้นโดยไม่มีecho -e "..."บรรทัดเพิ่มเติมใด ๆ มันกะทัดรัดกว่าในสถานการณ์เหล่านั้น
slm

6
hold=' '
printf "Press 'SPACE' to continue or 'CTRL+C' to exit : "
tty_state=$(stty -g)
stty -icanon
until [ -z "${hold#$in}" ] ; do
    in=$(dd bs=1 count=1 </dev/tty 2>/dev/null)
done
stty "$tty_state"

ตอนนี้พิมพ์พรอมต์โดยไม่ขึ้นบรรทัดใหม่จัดการCTRL+Cอย่างน่าเชื่อถือเรียกใช้งานได้sttyบ่อยเท่าที่จำเป็นและคืนค่าการควบคุม tty ให้ตรงกับสถานะที่sttyพบ ค้นหาman sttyข้อมูลเกี่ยวกับวิธีควบคุม echoes อักขระควบคุมและทั้งหมดอย่างชัดเจน

คุณอาจทำสิ่งนี้:

printf "Press any key to continue or 'CTRL+C' to exit : "
(tty_state=$(stty -g)
stty -icanon
LC_ALL=C dd bs=1 count=1 >/dev/null 2>&1
stty "$tty_state"
) </dev/tty

คุณสามารถทำได้ด้วยENTERไม่มี[การทดสอบ]และไม่sttyชอบ:

sed -n q </dev/tty

5

คุณสามารถสร้างฟังก์ชั่นได้:

pause(){
 read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
}

จากนั้นคุณสามารถใช้สิ่งนี้ได้ทุกที่ในสคริปต์ของคุณ:

pause

ถ้าคุณยังใหม่กับการเขียนสคริปต์เชลล์ - คุณต้องใส่ฟังก์ชั่นที่ด้านบนสุดของสคริปต์ก่อนที่จะใช้
Richard

3

ขี้เกียจหนึ่งซับ:

echo "Press any key to continue or Ctrl+C to cancel"
read && do_something.sh

ข้อเสียคือคุณสูญเสียการควบคุมเมื่อผู้ใช้กด ctrl + c สคริปต์จะออกด้วยรหัส 130 เสมอในกรณีนั้น


2

การตั้งค่าIFSเป็นสตริงว่างไม่แสดงพฤติกรรมเริ่มต้นของการตัดพื้นที่สีขาวของผู้อ่าน

try_this() {
  echo -n "Press SPACE to continue or Ctrl+C to exit ... "
  while true; do
    # Set IFS to empty string so that read doesn't trim
    # See http://mywiki.wooledge.org/BashFAQ/001#Trimming
    IFS= read -n1 -r key
    [[ $key == ' ' ]] && break
  done
  echo
  echo "Continuing ..."
}
try_this

อัปเดต 2018-05-23: เราสามารถทำให้สิ่งนี้ง่ายขึ้นโดยใช้ตัวแปร REPLY ซึ่งไม่ขึ้นอยู่กับการแบ่งคำ:

try_this() {
  echo -n "Press SPACE to continue or Ctrl+C to exit ... "
  while true; do
    read -n1 -r
    [[ $REPLY == ' ' ]] && break
  done
  echo
  echo "Continuing ..."
}
try_this

1

นี่คือวิธีที่ใช้งานได้ทั้งในbashและzshและทำให้แน่ใจว่า I / O กับเทอร์มินัล:

# Prompt for a keypress to continue. Customise prompt with $*
function pause {
  >/dev/tty printf '%s' "${*:-Press any key to continue... }"
  [[ $ZSH_VERSION ]] && read -krs  # Use -u0 to read from STDIN
  [[ $BASH_VERSION ]] && </dev/tty read -rsn1
  printf '\n'
}
export_function pause

ใส่ไว้ในของคุณ.{ba,z}shrcเพื่อความยุติธรรม!

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