Làm cách nào để tôi nhập n lặp lại một chữ số trong bash, tương tác


20

Tôi muốn chạy lệnh

foo --bar=baz <16 zeroes>

Làm cách nào để tôi nhập 16 số 0 một cách hiệu quả *? Nếu tôi giữ Altvà nhấn 1 6 0nó sẽ lặp lại điều tiếp theo 160 lần, đó không phải là điều tôi muốn. Trong emacs tôi có thể sử dụng Alt-[number]hoặc Ctrl-u 1 6 Ctrl-u 0, nhưng trong bash Ctrl-usẽ giết chết dòng đang được gõ và số 0 tiếp theo chỉ cần thêm 0 vào dòng.

Nếu tôi làm

foo --bar=baz $(printf '0%.0s' {1..16})

Sau đó historyhiển thị chính xác ở trên, và không foo --bar=baz 0000000000000000; tức là bash không hành xử theo cách tôi muốn. ( Chỉnh sửa : điểm đang tồn tại, tôi muốn nhập một số số không mà không sử dụng $(...)thay thế lệnh)

. ví dụ emacs đủ điều kiện là hiệu quả theo định nghĩa này.


1
Âm thanh như bạn muốn bash chỉ bằng cách nào đó know what you want to do. Trong một lệnh lồng nhau phức tạp, làm thế nào bash biết phần nào bạn muốn xem kết quả của việc thực hiện trong lịch sử trái ngược với chính lệnh đó? Còn các biến thì sao? Trong bash ngắn sẽ luôn luôn có codetrong lịch sử, không phải là kết quả của việc thực thi mã.
không tin

@meuh, Alttự nó không gửi bất kỳ ký tự nào, vì vậy, nhấn và phát hành alt sẽ không có bất kỳ ảnh hưởng nào bash.
Stéphane Chazelas

1
@Unbeliever Hãy làm những gì tôi muốn nói và nó sẽ ổn thôi
mèo

@Unbeliever: xem phần chỉnh sửa của tôi, điểm của đoạn phải làm historylà tôi muốn nhập các chữ số mà không sử dụng thay thế lệnh.
Jonas Kölker

Bất cứ khi nào bạn muốn mọi thứ được gõ tự động cho bạn, AutoKey là một tiện ích tuyệt vời để sử dụng. Với nó, bạn có thể xây dựng các thay thế cụm từ hoặc các macro Python hoàn chỉnh sẽ làm hầu hết mọi thứ bạn thích khi gõ cụm từ kích hoạt hoặc nhấn phím nóng. Tôi không bao gồm câu trả lời này vì nó yêu cầu môi trường máy tính để bàn GUI và các câu trả lời còn lại thì không - và do đó thường được áp dụng nhiều hơn.
Joe

Câu trả lời:


25

Thử

tiếng vang Alt+1Alt+6Ctrl+V0

Đó là 6 nét chính (giả sử ít nhất là bàn phím QWERTY của Hoa Kỳ / Vương quốc Anh) để chèn 16 số không (bạn có thể giữ Altcho cả 1 và 6).

Bạn cũng có thể sử dụng vichế độ tiêu chuẩn ( set -o vi) và gõ:

tiếng vang 0 Escx16p

(cũng có 6 nét chính).

Các emacschế độ tương đương và có thể được sử dụng để lặp lại hơn một ký tự đơn ( ) hoạt động trong , nhưng không phải trong .echo 0Ctrl+WAlt+1Alt+6Ctrl+Yzshbash

Tất cả những người cũng sẽ làm việc với zsh(và tcshnơi đó đến từ). Với zsh, bạn cũng có thể sử dụng các cờ mở rộng biến đệm và mở rộng chúng bằng Tab:

tiếng vang $ {(l: 16 :: 0 :)}Tab

(Rất nhiều tổ hợp phím rõ ràng hơn).

Với bash, bạn cũng có thể bashmở rộng $(printf '0%.0s' {1..16})với Ctrl+Alt+E. Lưu ý rằng mặc dù nó sẽ mở rộng tất cả mọi thứ (mặc dù không phải là ảm đạm) trên dòng.

Để chơi trò chơi có số lượng phím ít nhất, bạn có thể liên kết với một số phím một tiện ích mở rộng <some-number>Xtheo thời gian Xlặp lại <some-number>. Và có <some-number>trong cơ sở 36 để thậm chí giảm hơn nữa.

Với zsh(ràng buộc F8):

repeat-string() {
  REPLY=
  repeat $1 REPLY+=$2
}
expand-repeat() {
  emulate -L zsh
  set -o rematchpcre
  local match mbegin mend MATCH MBEGIN MEND REPLY
  if [[ $LBUFFER =~ '^(.*?)([[:alnum:]]+)(.)$' ]]; then
    repeat-string $((36#$match[2])) $match[3]
    LBUFFER=$match[1]$REPLY
  else
    return 1
  fi
}
zle -N expand-repeat
bindkey "$terminfo[kf8]" expand-repeat

Sau đó, cho 16 số không, bạn gõ:

tiếng vang g0F8

(3 tổ hợp phím), nơi g16ở cơ sở 36.

Bây giờ chúng ta có thể giảm thêm nó xuống một phím chèn 16 số không, mặc dù điều đó sẽ là gian lận. Chúng tôi có thể liên kết F2với hai 0(hoặc hai $STRING, 0 theo mặc định), F3đến 3 0giây, F1F6đến 16 0giây ... tối đa 19 ... khả năng là vô tận khi bạn có thể xác định các tiện ích tùy ý.

Có lẽ tôi nên đề cập rằng nếu bạn nhấn và giữ 0phím, bạn có thể chèn bao nhiêu số không như bạn muốn chỉ bằng một lần nhấn phím :-)


Cảm ơn đã cung cấp nhiều biến thể cho vivà những người khác!
Mark Stewart

9

Giả sử trình giả lập thiết bị đầu cuối của bạn không ăn tổ hợp phím (ví dụ: để chuyển tab) Công cụ xterm xterm hoạt động Bạn có thể nhấn Alt-1 6 Ctrl-V 0. Cần có control-V để chia số và ký tự lặp lại (nếu bạn đang lặp lại một chữ cái, bạn sẽ không cần nó).

(Đây là một tính năng đọc được gọi là digit-argument, vì vậy bạn sẽ có thể sử dụng bindđể thay đổi các phím bổ trợ có liên quan)


1
Cảm ơn bạn, bao gồm tên của tính năng này rất hữu ích khi những người như tôi vấp phải những câu hỏi này. Các liên kết liên quan để đọc thêm một chút: Hướng dẫn sử dụng Câu hỏibash
admalledd

4

Trong Emacs, tôi thường sử dụng C-qđể tách đối số tiền tố khỏi đầu vào chữ số.

Bash sử dụng Ctrl+vthay vì C-q, để tránh các vấn đề với điều khiển luồng XON / XOFF.

Vì vậy, bạn có thể sử dụng Alt+1 Alt+6 Ctrl+v 0.


3

một tùy chọn khác là gõ bốn số không và sau đó sử dụng chuột để sao chép và dán thêm ba lần nữa. bấm đúp chuột để chọn, bấm giữa x 3 để dán.


Hoặc đánh gôn / gian lận thêm một số bằng cách nhập một số 0, chọn và dán số đó để nhận 2; chọn và dán nó để có được 4; chọn và dán lên 8, và một lần nữa cho 16. Thật đáng tiếc :)
Jeff Schaller

vâng, nhưng gõ 4 số 0 và dán lại chúng có vẻ như là mức độ nỗ lực tối ưu so với mức chi trả cho tôi. tất cả những gì sao chép và dán thêm có vẻ như công việc.
cas

3

Chơi với macro:

Ràng buộc phím chức năng F8để nhân với hai từ cuối cùng (tăng khoảng trắng trước đó) (mã khóa F8 được tìm thấy bằng cách sử dụng Ctrl-V F8):

$ bind '"\e[19~": "\C-w\C-y\C-y"'

Điều đó có thể được thực hiện vĩnh viễn bằng cách gửi cùng một văn bản tới ~/.inputrc

$ echo '"\e[19~": "\C-w\C-y\C-y"' >> ~/.inputrc

sau đó gõ:

tiếng vang 0F8F8F8F8

để có được 2 ^ 4 lần số không. (vẫn còn 5 lần nhấn phím).

hoặc loại:

cuốn sách tiếng vangF8F8F8

để có được 2 ^ 3 từ sách.

Vẫn nhanh hơn:

Nhân với 4:

$ bind '"\e[19~": "\C-w\C-y\C-y\C-w\C-y\C-y"'

tiếng vang 0F8F8

3 phím bấm.

Nhân với 8 (cùng số với phím chức năng)

$ bind '"\e[19~": "\C-w\C-y\C-y\C-w\C-y\C-y\C-w\C-y\C-y"'

tiếng vang 00F8

Vẫn 3 phím bấm.

Lừa đảo?

Gian lận bằng cách nhân với 16.

$ bind '"\e[19~": "\C-w\C-y\C-y\C-w\C-y\C-y\C-w\C-y\C-y\C-w\C-y\C-y"'

tiếng vang 0F8

Chỉ có 2 phím bấm. (và vẫn là một chức năng đơn giản hữu ích)

^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^

Rõ ràng là gian lận:

$ bind '"\e[19~": "0000000000000000"'

tiếng vang F8

Chỉ cần 1 (có: một ) tổ hợp phím.



Thay đổi ràng buộc cho ctrl+U:

Gửi cái này đến ~/.inputrc:

echo '"\C-u": universal-argument >> ~/.inputrc

Đọc lại ~/.inputrctập tin:

ctrl+Xctrl+R

làm điều đó như bình thường trong emacs (như bạn muốn):

foo --bar = baz ctrl+U16 ctrl+U0

7 phím (sau khi "thiết lập").

Hơi ngắn hơn một chút:

Sử dụng "nhân với 4" mặc định của "đối số phổ quát" và kết thúc bằng

 ctrl+V 0 

foo --bar = baz ctrl+Uctrl+Uctrl+V0

Chỉ có 5 phím.

Sử dụng alt+nquyền truy cập vào (arg: n)

foo --bar = baz Alt+16Ctrl+V0

Đó là 6 chìa khóa để có được 16 số không.

Không thay đổi bất kỳ phím tắt nào:

Nếu trong bash của bạn, bạn có bash C-u kills the currently-being-typed line.
Đó là bởi vì "\C-u":được liên kết với unix-line-discard.

Nhưng điều đó cũng có thể giúp ích:
Khi nào, cái gì trước khi con trỏ bị xóa, nó cũng được đặt trong "vòng giết".

Vì vậy, ctrl+uxóa và ctrl+ykéo lại những gì đã bị xóa.
Trên một dòng sạch: Gõ 00xóa nó và kéo nó trở lại hai lần để thực hiện 0000.
Lặp lại để nhận 00000000(8 số không), cuối cùng gõ lệnh và quay lại hai lần.

Bộ đầu tiên ( ctrlnhấn 7 phím ):

00 ctrl+Uctrl+Yctrl+Y ctrl+U 

Bộ thứ hai (5 phím)

ctrl+Uctrl+Yctrl+Y ctrl+U 

Điều đó sẽ nhận được tám số không trong vòng xóa, sau đó nhập những gì bạn muốn:

 foo - bar = baz ctrl-Y ctrl-Y 

để có được:

foo --bar=baz 0000000000000000

Sau khi bạn có ý tưởng, bạn cũng có thể, nhập những gì bạn cần, đi đến đầu dòng ( ctrl-Y), làm như trên (tối đa tám số không) đi đến cuối ( ctrl-E) và kéo dài hai lần.

foo --bar = baz ctrl-A00ctrl-Uctrl-Yctrl-Y ctrl-Uctrl-Yctrl-Y ctrl-U ctrl-Ectrl-Yctrl-Y

Đó là 15 phím (bên cạnh lệnh).
Không ngắn, tôi biết, nhưng đó chỉ hoạt động với những gì đã có sẵn.

Cái này ngắn hơn một chút:

0000 ctrl-U ctrl-Y ctrl-Y ctrl-Y ctrl-Yctrl-A foo --bar = baz

Đó là 11 phím


Xem chỉnh sửa câu trả lời của tôi ;-)
Stéphane Chazelas

@ StéphaneChazelas Sử dụng macro? Căn cứ 36? Chỉ trong zsh? Thôi nào ... xem bản chỉnh sửa của tôi :-P
sorontar

Vâng, cơ sở36 là một chút lưỡi trong má. Tôi thích việc bạn F<n>nhân đôi lần cuối từ <n>.
Stéphane Chazelas

Lưu ý rằng không phải tất cả các thiết bị đầu cuối đều gửi cùng một chuỗi trên F8 (mặc dù hầu hết các thiết bị được tìm thấy trên các hệ thống GNU / Linux đều gửi ^[[19~). Xem "$(tput kf8)"để lấy thông tin từ cơ sở dữ liệu terminfo (hoặc $terminfohàm băm trong zsh).
Stéphane Chazelas

@ StéphaneChazelas Vâng, điều đó đúng. Hoặc đơn giản là sử dụngctrl-v F8
sorontar

2

Là một biến thể của câu trả lời của cas , gõ

printf '0% .s' {1..16}Enter
và sau đó sử dụng chuột để sao chép và dán nó (một lần). Có thể cho rằng, đây là O (log n), nhưng vì nó là (len (str (n)) + 20), nên bạn có thể coi nó không hiệu quả. Nhưng lưu ý:

  • Tôi đã có thể cạo sạch một nhân vật - trên hệ thống của tôi, %.sdường như hành xử giống như %.0s.
  • Nếu bạn muốn chạy nhiều lệnh với 0000000000000000tư cách là một đối số, bạn chỉ cần thực hiện việc này một lần.

glenn jackman chỉ ra rằng (trong đó số là số nguyên dương) sẽ in một chuỗi số không (và một dòng mới), vì dấu hoa thị trong định dạng cho biết lấy chiều rộng trường từ các đối số. Cụ thể, sẽ in 16 số không. Nhưng đây là một trường hợp đặc biệt mà chỉ xử lý .  sẽ in và sẽ in và thông báo lỗi. Ngược lại, các lệnh khác trong câu trả lời này sẽ tạo ra các chuỗi như hoặc (và xem bên dưới cho ).printf "%0*d\n" number 0printfprintf "%0*d" 16 0 0printf "%0*d" 16 123450000000000012345printf "%0*d" 16 foo0000000000000000123451234512345…foofoofoo…7%7%7%...

Nếu bạn thường xuyên làm điều này, bạn có thể hợp lý hóa nó bằng cách xác định hàm shell:

rep() { printf -- "$1%.0s" $(seq 1 "$2"); printf "\n"; }

Ghi chú:

  • Sử dụng $(seq 1 "$2")thay (1.."$2"}vì bởi vì cái sau sẽ không hoạt động - xem cái này , cái này , cái nàycái này . Lưu ý rằng một số câu trả lời cho những câu hỏi gợi ý sử dụng eval, nhưng điều này thường không được khuyến khích.
  • Chuỗi định dạng ( $1%.0s) phải ở trong dấu ngoặc kép (chứ không phải dấu ngoặc đơn) vì nó chứa tham số ( $1).
  • Các --là để chống lại bảo vệ$1 các giá trị bắt đầu với -.
  • Bạn có thể có được sự bảo vệ tương tự bằng cách sử dụng "%.0s$1" thay vì "$1%.0s".
  • Dù bằng cách nào, một $1 giá trị có chứa %sẽ khiến nó bị sặc.
  • Nếu bạn cần có khả năng xử lý $1các giá trị có chứa %, hãy làm

    rep() { local i; for ((i=0; i<$2; i++)); do printf '%s' "$1"; done; printf "\n"; }

Ngoài ra, một khi bạn có một chức năng như vậy được xác định, bạn có thể làm những việc như

foo --bar=baz "$(rep 0 16)"

đó là gõ ít hơn một chút so với "$(printf '0%.0s' {1..16})".


Thay phiên printf "%0*d" 16 0sẽ in 16 số không. Dấu hoa thị ở định dạng sẽ lấy chiều rộng trường từ các đối số
glenn jackman
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.