Linux tương đương với tạm dừng DOS là gì?


236

Tôi có một tập lệnh shell Bash trong đó tôi muốn tạm dừng thực thi cho đến khi người dùng nhấn một phím. Trong DOS, điều này dễ dàng được thực hiện bằng lệnh "tạm dừng". Có một Linux tương đương tôi có thể sử dụng trong kịch bản của mình không?

Câu trả lời:


329

read thực hiện điều này:

user@host:~$ read -n1 -r -p "Press any key to continue..." key
[...]
user@host:~$ 

Việc -n1xác định rằng nó chỉ chờ một ký tự duy nhất. Việc -rđặt nó vào chế độ thô, điều này là cần thiết bởi vì nếu không, nếu bạn nhấn một cái gì đó như dấu gạch chéo ngược, nó sẽ không đăng ký cho đến khi bạn nhấn phím tiếp theo. Các -pquy định cụ thể các dấu nhắc, mà phải được trích dẫn nếu nó chứa dấu cách. Đối keysố chỉ cần thiết nếu bạn muốn biết họ đã nhấn phím nào, trong trường hợp nào bạn có thể truy cập thông qua $key.

Nếu bạn đang sử dụng Bash, bạn cũng có thể chỉ định thời gian chờ với -t, điều này khiến cho việc đọc trở lại thất bại khi nhấn phím. Ví dụ:

read -t5 -n1 -r -p 'Press any key in the next five seconds...' key
if [ "$?" -eq "0" ]; then
    echo 'A key was pressed.'
else
    echo 'No key was pressed.'
fi

5
Nói đúng ra, đó sẽ là "Enter any non-NUL character to continue". Một số phím không gửi bất kỳ ký tự nào (như Ctrl...) và một số phím gửi nhiều hơn một (như F1, Home...). bashbỏ qua các ký tự NUL.
Stephane Chazelas

2
Thông thường, nên hỏi một khóa cụ thể như enter, space hoặc Y. "ANY" có thể gây nhầm lẫn cho một số người dùng, có một phím TAB vậy tại sao không có khóa BẤT K and và chắc chắn có những khóa có khả năng gây nguy hiểm như ESCAPE, CTRL, CMD, nút nguồn, v.v. Điều này không còn phù hợp nữa ngày nay, vì ngày nay giao diện điều khiển thường chỉ được sử dụng bởi những người dùng máy tính tiên tiến sẽ hiểu chính xác "BẤT K key phím". Hướng dẫn thiết kế Apple 2, khá cũ, có một phần thú vị dành cho chủ đề này ( apple2scans.net/files/1982-A2F2116-m-a2e-aiiedg.pdf ).
Gellweiler

3
Thay vào đó, nếu bạn sử dụng tin nhắn Press a key to continue...thì ngay cả người dùng mới làm quen cũng có thể tìm thấy aphím và bấm nó; o)
DJDaveMark

1
Điều này sẽ có vấn đề với command | myscript.shhoặc myscript.sh | command. Xem câu trả lời này cho một giải pháp.
Tom Hale

Nếu bất cứ ai được read: 1: read: Illegal option -nđảm bảo bọc lệnh của bạn trong bash -c 'command && command'vv vì lỗi đó có thể xảy ra sh. Tôi đang làm điều này trong một lệnh bao bọc Lando.
Elijah Lynn

155

Tôi sử dụng những cách này rất ngắn, và chúng giống như các giải pháp @theunamedguy và @Jim, nhưng ngoài ra còn có chế độ chờ và chế độ im lặng.

Tôi đặc biệt yêu thích trường hợp cuối cùng và sử dụng nó trong rất nhiều tập lệnh chạy trong một vòng lặp cho đến khi người dùng nhấn Enter.

Các lệnh

  • Nhập giải pháp

    read -rsp $'Press enter to continue...\n'
  • Giải pháp thoát hiểm (với -d $ '\ e')

    read -rsp $'Press escape to continue...\n' -d $'\e'
  • Bất kỳ giải pháp chính nào (với -n 1)

    read -rsp $'Press any key to continue...\n' -n 1 key
    # echo $key
  • Câu hỏi với lựa chọn được chọn trước (với -ei $ 'Y')

    read -rp $'Are you sure (Y/n) : ' -ei $'Y' key;
    # echo $key
  • Giải pháp hết thời gian (với -t 5)

    read -rsp $'Press any key or wait 5 seconds to continue...\n' -n 1 -t 5;
  • Bí danh tăng cường giấc ngủ

    read -rst 0.5; timeout=$?
    # echo $timeout

Giải trình

-r chỉ định chế độ thô, không cho phép các ký tự kết hợp như "\" hoặc "^".

-s chỉ định chế độ im lặng và vì chúng tôi không cần đầu ra bàn phím.

-p $ ' prompt ' chỉ định lời nhắc, cần nằm trong khoảng $ 'và' để cho phép khoảng trắng và ký tự thoát. Hãy cẩn thận, bạn phải đặt giữa các dấu ngoặc đơn với ký hiệu đô la để mang lại lợi ích cho các ký tự thoát, nếu không bạn có thể sử dụng các trích dẫn đơn giản.

-d $ ' \ e ' chỉ định escappe là ký tự phân cách, vì vậy là ký tự cuối cùng cho mục nhập hiện tại, điều này có thể đặt bất kỳ ký tự nào nhưng hãy cẩn thận để đặt một ký tự mà người dùng có thể nhập.

-n 1 chỉ định rằng nó chỉ cần một ký tự duy nhất.

-e chỉ định chế độ đọc.

-i $ ' Y ' chỉ định Y là văn bản ban đầu ở chế độ đọc.

-t 5 chỉ định thời gian chờ là 5 giây

phục vụ khóa trong trường hợp bạn cần biết đầu vào, trong trường hợp -n1, phím đã được nhấn.

$? phục vụ để biết mã thoát của chương trình cuối cùng, để đọc, 142 trong trường hợp hết thời gian, 0 đầu vào đúng. Đặt $? trong một biến càng sớm càng tốt nếu bạn cần kiểm tra nó sau các lệnh somes, bởi vì tất cả các lệnh sẽ viết lại $?


1
+1 để giải thích -s; man readread --helptrợ giúp đã không giúp đỡ trên Ubuntu 10.04.1 LTS. Chỉnh sửa: help readđã làm; phần còn lại không được chấp nhận?
Cees Timmerman

1
1+ cho lời giải thích tuyệt vời: nhưng tôi đã nhận read: -i: invalid optioncho người cũ. read -rp $'Are you sure (Y/n) : ' -ei $'Y' key;thay vào đó, #osx read -rp $'kill-server: Are you sure (Y/n) : ' -d $'Y' key;hoạt động với tôi. `
Tino Rzig

Tôi không biết nó hoạt động như thế nào trên OSX nhưng tôi đã thực hiện một số thử nghiệm và -ihoạt động hoàn hảo trên Ubuntu, tôi cũng không biết làm thế nào nếu -dhoạt động tương tự trên OSX.
y.petremann

người ta có thể làm việc xung quanh nhanh chóng và tốt đẹp bằng cách sử dụng tiếng vang trước khi đọc, cuối cùng là tiếng vang -n
THESorcerer

15

readkhông có bất kỳ tham số nào sẽ chỉ tiếp tục nếu bạn nhấn enter. Lệnh DOS pausesẽ tiếp tục nếu bạn nhấn bất kỳ phím nào. Sử dụng read –n1nếu bạn muốn hành vi này.


15

Điều này làm việc cho tôi về nhiều hương vị của Linux, trong đó một số giải pháp khác không có (bao gồm cả những giải pháp phổ biến nhất ở đây). Tôi nghĩ nó cũng dễ đọc hơn ...

echo Press enter to continue; read dummy;

Lưu ý rằng một biến cần được cung cấp làm đối số read.


câu trả lời này giải quyết vấn đề của tôi, nếu tôi sao chép và dán dòng này và vì một số lý do tôi đã thêm nhiều dòng, các dòng được nối không được thực thi, giống như với tạm dừng DOS
Sérgio

10

read -n1không phải là di động. Một cách di động để làm điều tương tự có thể là:

(   trap "stty $(stty -g;stty -icanon)" EXIT
    LC_ALL=C dd bs=1 count=1 >/dev/null 2>&1
)   </dev/tty

Bên cạnh việc sử dụng read, chỉ cần nhấn ENTERđể tiếp tục nhắc bạn có thể làm:

sed -n q </dev/tty

2
status=nonecũng không phải là di động. Thay vào đó, chuyển hướng stdout và stderr sang / dev / null. read -r line < /dev/ttysẽ là enought cho nhấn ENTER ... .
Stephane Chazelas

@StephaneChezales cảm ơn - tôi không biết điều đó. tôi sẽ sửa nó ngay. Cảm ơn một lần nữa - đã sửa. Nhân tiện, bạn cũng là một thông tin đáng giá.
mikeerv

1
Cũng lưu ý settings=$(stty -g); stty raw; dd ...; stty "$settings"để lưu và khôi phục cài đặt tty.
Stephane Chazelas

@StephaneChezales - tôi không ở máy tính - bạn có nghĩ rằng trchỉnh sửa cũng có thể hoạt động không?
mikeerv

1
Không, bởi vì trsẽ đệm đầu ra của nó dưới dạng ống và bàn phím không phải của Hoa Kỳ có các phím gửi ký tự ngoài \1-\177phạm vi. ddlà cách thành ngữ ở đây.
Stephane Chazelas

2

Nếu bạn chỉ cần tạm dừng một vòng lặp hoặc tập lệnh và bạn vui lòng nhấn Enter thay vì bất kỳ phím nào, thì readchính nó sẽ thực hiện công việc.

do_stuff
read
do_more_stuff

Nó không thân thiện với người dùng cuối, nhưng có thể là đủ trong trường hợp bạn tự viết một tập lệnh nhanh và bạn cần tạm dừng nó để làm một cái gì đó thủ công trong nền.


Điều này là đúng, nhưng đối với cơ sở dữ liệu, nó hữu ích nhất để hiển thị một ví dụ.
SDsolar 27/03/18

Cảm ơn, tôi đã đưa lời khuyên của bạn lên tàu. Chỉ viết một tên lệnh không rõ ràng lắm.
mwfearnley

1

Thử cái này:

function pause(){
   read -p "$*"
}

1
Ai đó có thể vui lòng giải thích tại sao điều này được hạ cấp? Là vì ​​thiếu nội dung hay đây là một giải pháp tồi?
3ocene

4
@ 3ocene Điều này không hiển thị việc sử dụng chức năng được tạo; cộng với điều này thiếu bất kỳ lời giải thích.
parvus

Đã đồng ý. Bạn có thể vui lòng chỉ ra một ví dụ về cách hàm này được gọi không?
SDsolar

1

Hàm này hoạt động trong cả hai bashzsh, và đảm bảo I / O cho thiết bị đầu cuối:

# 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

Đặt nó trong .{ba,z}shrcCông lý vĩ đại của bạn !


0

Có để sử dụng read- và có một vài điều chỉnh làm cho nó hữu ích nhất trong cả cronvà trong thiết bị đầu cuối.

Thí dụ:

time rsync (options)
read -n 120 -p "Press 'Enter' to continue..." ; echo " "

-N 120 làm cho câu lệnh đọc hết thời gian sau 2 phút để nó không bị chặn cron.

Trong terminal, nó cho 2 phút để xem rsynclệnh mất bao lâu để thực thi.

Sau đó, tiếp theo echolà vì vậy dấu nhắc bash tiếp theo sẽ xuất hiện trên dòng tiếp theo.

Nếu không, nó sẽ hiển thị trên cùng một dòng ngay sau khi "tiếp tục ..." khi Enterđược nhấn trong thiết bị đầu cuối.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.