Làm thế nào để tôi có được các dòng lệnh dài để bọc đến dòng tiếp theo?


108

Một điều mà tôi đã nhận thấy trong Ubuntu trong một thời gian dài khiến tôi bực bội là khi tôi gõ một lệnh tại dòng lệnh dài hơn (rộng hơn) so với chiều rộng của thiết bị đầu cuối, thay vì gói vào một dòng mới, nó sẽ quay trở lại cột 1 trên cùng một dòng và bắt đầu ghi đè lên đầu dòng lệnh của tôi. (Nó không thực sự ghi đè lên lệnh thực tế, nhưng về mặt trực quan, nó ghi đè lên văn bản đã được hiển thị).

Thật khó để giải thích mà không nhìn thấy nó, nhưng giả sử thiết bị đầu cuối của tôi rộng 20 ký tự (Của tôi giống như 120 ký tự - nhưng vì lợi ích của một ví dụ), và tôi muốn lặp lại bảng chữ cái tiếng Anh. Những gì tôi gõ là đây:

echo abcdefghijklmnopqrstuvwxyz

Nhưng thiết bị đầu cuối của tôi trông như thế nào trước khi tôi nhấn phím là:

pqrstuvwxyzghijklmno

Khi tôi nhấn enter, nó vang

abcdefghijklmnopqrstuvwxyz

vì vậy tôi biết lệnh đã được nhận đúng. Nó chỉ ngắt kiểu gõ của tôi sau chữ "o" và bắt đầu lại trên cùng một dòng.

Điều tôi mong đợi sẽ xảy ra, nếu tôi gõ lệnh này trên một thiết bị đầu cuối chỉ rộng 20 ký tự thì đây sẽ là:

echo abcdefghijklmno
pqrstuvwxyz

Bối cảnh: Tôi đang sử dụng bash làm vỏ của mình và tôi có dòng này trong ~ / .bashrc:

set -o vi

để có thể điều hướng dòng lệnh bằng các lệnh VI. Tôi hiện đang sử dụng máy chủ Ubuntu 10.10 và kết nối với máy chủ bằng Putty.

Trong bất kỳ môi trường nào khác mà tôi đã làm việc, nếu tôi gõ một dòng lệnh dài, nó sẽ thêm một dòng mới bên dưới dòng tôi đang làm việc khi lệnh của tôi dài hơn chiều rộng của thiết bị đầu cuối và khi tôi tiếp tục gõ, tôi có thể thấy lệnh của mình trên 2 dòng khác nhau. Nhưng miễn là tôi có thể nhớ sử dụng Ubuntu, các lệnh dài của tôi chỉ chiếm 1 dòng.

Điều này cũng xảy ra khi tôi quay lại các lệnh trước đó trong lịch sử (tôi nhấn Esc, sau đó 'K' để quay lại các lệnh trước đó) - khi tôi nhận được lệnh trước dài hơn độ rộng của thiết bị đầu cuối, dòng lệnh sẽ đọc sai và tôi không thể biết tôi đang ở đâu trong lệnh.

Công việc duy nhất tôi tìm thấy để thấy toàn bộ lệnh dài là nhấn "Esc-V", mở ra lệnh hiện tại trong trình soạn thảo VI.

Tôi không nghĩ rằng tôi có bất cứ điều gì kỳ lạ trong tệp .bashrc của mình. Tôi đã nhận xét dòng "set -o vi" và tôi vẫn gặp sự cố.

Tôi đã tải xuống một bản sao mới của Putty và không thực hiện bất kỳ thay đổi nào đối với cấu hình - Tôi chỉ cần nhập tên máy chủ của mình để kết nối và tôi vẫn gặp sự cố, vì vậy tôi không nghĩ đó là bất cứ điều gì với Putty (trừ khi tôi cần thực hiện một số thay đổi cấu hình)

Có ai khác có vấn đề này, và bất cứ ai có thể nghĩ làm thế nào để khắc phục nó?

Biên tập

Đó là tập tin .bashrc của tôi. Tôi đã sao chép cùng một hồ sơ từ máy này sang máy khác và tôi đã sử dụng các ký tự đặc biệt trong $ PS1 của mình bằng cách nào đó loại bỏ nó. Bây giờ tôi đang gắn bó với các biến bash tiêu chuẩn cho $ PS1 của mình.

Cảm ơn @ ndrük về mẹo trên .bashrc!

... Kết thúc chỉnh sửa ...


1
Để chắc chắn rằng sự cố không phải do tệp .bashrc của bạn gây ra, tôi khuyên bạn nên tạm thời thay thế nó bằng một bản sao /etc/skel/.bashrc. Hãy nhớ rằng bạn sẽ cần kết nối lại để các thay đổi có hiệu lực và đảm bảo giữ bản sao lưu .bashrc của riêng bạn.
ændrük

1
Bạn đang sử dụng ứng dụng thiết bị đầu cuối nào? Hành vi bạn đang mô tả không bình thường, chắc chắn không phải là mặc định.
João Pinto

Trong các shell mà tôi đã làm việc (và trong Cisco CLI), bạn cũng có thể nhập Ctrl-L để hiển thị lại dòng bạn đang gõ, ngay cả khi nó ngoài màn hình. Trong tình huống của bạn, điều đó vẫn có thể tạo ra đầu ra bị hỏng mà bạn đang nói đến, nhưng tôi tò mò.
belacqua

3
Hãy thoải mái tạo ra một "câu trả lời" giải thích giải pháp và đánh dấu nó là được chấp nhận. Nó có vẻ hơi ngớ ngẩn, nhưng có một câu trả lời thích hợp giúp giữ cho trang web được tổ chức và có thể hướng dẫn hiệu quả hơn những người khác có vấn đề tương tự trong tương lai.
ændrük

Theo câu trả lời này trên serverfault , hãy sử dụngtput smam
Samveen

Câu trả lời:


136

Đảm bảo rằng tất cả các byte không in được trong PS1 của bạn được chứa trong đó \[ \]. Nếu không, bash sẽ tính chúng theo chiều dài của dấu nhắc. Nó sử dụng độ dài của dấu nhắc để xác định thời điểm quấn dòng.

Ví dụ: ở đây bash đếm dấu nhắc là 19 cột rộng, trong khi dấu nhắc được hiển thị bởi thiết bị đầu cuối chỉ rộng 10 cột ( My promptđược viết bằng màu lục lam và >được viết bằng màu mặc định):

PS1='\e[36mMy prompt\e[0m>'         # bash count: 19, actual: 10

trong khi ở đây, nó chỉ đếm dấu nhắc là 10 cột rộng vì nó bỏ qua các byte giữa đặc biệt \[\]thoát:

PS1='\[\e[36m\]My prompt\[\e[0m\]>' # bash count: 10, actual: 10

Đối với thực tiễn tốt, sử dụng tputđể tạo ra các thiết bị đầu cuối thoát chứ không phải mã hóa cứng:

cyan=$(tput setaf 6) # \e[36m
reset=$(tput sgr0)   # \e[0m
PS1='\[$cyan\]My prompt\[$reset\]>'

Xem http://mywiki.wooledge.org/BashFAQ/053http://wiki.bash-hackers.org/scripting/terminalcodes để biết thêm về tput.


3
Đó là một lời giải thích tuyệt vời về vấn đề mà câu trả lời được chấp nhận không cung cấp
Jamie Cook

Trong dòng mã cuối cùng PS1='...': tại sao các trích dẫn đơn không ngăn chặn $cyan$resetthay thế?
andrybak

2
@andrybak, chúng ngăn chặn $cyan$resetthay thế, nhưng PS1được đánh giá mỗi khi dấu nhắc được in. Bạn có thể thấy điều này bằng cách thử PS1='$var> 'và sau đó đưa ra varcác giá trị khác nhau và xem cách nhắc nhở thay đổi. Sau đó thử PS1="$var> " và nhận thấy rằng dấu nhắc vẫn tĩnh; $varđược mở rộng trong quá trình chuyển nhượng, không phải lúc nào PS1cũng được đánh giá.
geirha

1
Thật đáng kinh ngạc. Cảm ơn rất nhiều vì đã gửi bài này! Nó làm cho việc thoát khỏi dấu ngoặc vuông dễ dàng hơn và dễ đọc hơn.
phyatt

Làm thế nào tôi làm cho công việc này PS1=${PS1}"\e]2;$@\a". Tôi đã thửPS1=${PS1}"\[\e]2;\]$@\[\a\]"
Ramana Reddy

59

Tôi đoán bạn đã cấu hình của bạn PS1với màu sắc, phải không?

Chỉ cần chắc chắn rằng bạn có \[trong PS1trích dẫn của bạn trước bộ màu của bạn

Ví dụ:

PS1='\[\e[0;32m\u@\w/:\[\e[m '

PS1 của tôi là export PS1='^[[96m'$(hostname)'<^[[92m${PWD}^[[96m>^[[97m '- Tôi đã sử dụng cái đó trong một thời gian dài - nó tương thích với KSH ...
BrianH

2
Ồ Tôi đã sử dụng lời nhắc thiết bị đầu cuối mãi mãi và chưa bao giờ gặp vấn đề này trước đây. Sẽ không bao giờ tìm ra điều đó. Cảm ơn.
beclill

3
sử dụng \ [trong khi sử dụng dấu ngoặc đơn giản sẽ tạo ra dấu gạch chéo ngoài ý muốn. Ngoài ra, nên được sử dụng] vào cuối các ký tự ma thuật, như đã lưu ý trong câu trả lời được bình chọn tốt nhất
igorsantos07

2
-1 Không hoạt động. Bạn cần bọc phần không in với \[lúc bắt đầu và \]ở cuối.
wjandrea

@ igorsantos07 Dấu gạch chéo kép trong \\[là lỗi chính tả do chỉnh sửa. Tôi đã sửa nó.
wjandrea

11

Tôi đã có một vấn đề tương tự, và cuối cùng tìm thấy một giải pháp đơn giản.

Thêm dòng sau vào .bashrctệp của bạn :

COLUMNS=250

Sau đó gõ source ~/.bashrcđể có được hiệu quả mong muốn.


Trong một số trường hợp, chẳng hạn như các phân chia terminator hẹp, vấn đề không nằm ở các ký tự màu promt mà chỉ ở một giá trị COLUMNS sai. Câu trả lời này đã đưa tôi ra khỏi một lỗ rất phiền!
Carles Sala

1
Đăng xuất là không cần thiết. Làm source .bashrc. Lời nhắc của bạn sẽ cập nhật ngay lập tức
Sergiy Kolodyazhnyy

1
Tôi thấy rằng vì tôi đã không setwinsizethiết lập shopt cho bash của mình, vì vậy nó không cập nhật đúng màu, hãy xem unix.stackexchange.com/a/167911/8337
rogerdpack

1
Tôi đã làm export COLUMNS=250theo export TERM=xtermvà nó rất hạnh phúc.
Philip Kearns

5

Tôi gặp vấn đề tương tự với một dấu nhắc màu tùy chỉnh, mặc dù tôi có chứa mã màu bên trong \[\]dấu phân cách. Nó chỉ ra rằng bash có vấn đề lặp lại màu sắc từ bên trong một chức năng . Cuối cùng tôi chỉ sử dụng các biến cho lời nhắc của mình và mặc dù .bashrc của tôi kém thanh lịch hơn một chút, mọi thứ đều hoạt động tốt.


Nếu bất cứ ai vẫn đọc được điều này, thực sự có thể thoát màu trong một hàm. Xem câu trả lời này trên câu hỏi liên kết.
wjandrea

3

Một điều đơn giản cần làm là thêm dòng sau đây trước khi đặt PS1:

stty columns 1000

Ví dụ,

stty columns 1000
PS1='\[\e[0;32m\u@\w/:[\e[m '

tuy nhiên điều này không ảnh hưởng đến các lệnh unix khác như ls và man.


1
Điều đó hoạt động trong OSX.
raskhadafi

4
Điều này cũng ảnh hưởng xấu đến vim. Xin đừng sử dụng cái này.
vừa rồi

0

Tôi đã có vấn đề này khi kết nối trong tmux. Vấn đề là tôi đã có một ipythonphiên trong nền ( ctrl + z) và bằng cách nào đó đã phá vỡ gói kết thúc. Ngay sau khi tôi chấm dứt nó fg, ( ctrl+d+dthiết bị đầu cuối của tôi đã bắt đầu hoạt động bình thường

Vì vậy, kiểm tra cho bất kỳ lời nhắc tương tác đã dừng.


0

Vì vậy, tôi chỉ gặp vấn đề tương tự với một chút thay đổi và tôi nghĩ tôi cũng sẽ chia sẻ giải pháp của mình, chỉ để thêm sắc thái nhỏ của mình: D

PS1 ban đầu của tôi là

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$"

Vấn đề tôi gặp phải là tôi đã cố gắng thay đổi tiêu đề thiết bị đầu cuối cũng như dấu nhắc lệnh. Cách tôi đã làm điều này là bằng cách thêm \[\033]0;\]Title\avào biến PS1 .

Vì vậy, bây giờ PS1 của tôi là:

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[\033]0;\]Title\a"

Điều này làm rối tung các gói cho tôi. Cuối cùng tôi đã nhận ra rằng bash dường như không thích có \acuối cùng. Để phá vỡ điều này, tôi đặt tiêu đề trong một biến, dường như để sửa nó.

TITLE="\033]0;Title\a"
PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[$TITLE\]"

0

\[\]đã không làm việc cho tôi. Tôi đoán có điều gì đó khác biệt về cách tôi tạo lời nhắc (từ một chương trình bên ngoài) hoặc bởi vì lời nhắc của tôi là "động".

Sau khi đọc điều này tôi thấy rằng bạn thực sự có thể thoát mã màu bằng 0x010x02byte.

ví dụ: Tôi đang sử dụng một phiên bản đặc biệt của Phấn và tôi bọc các màu bằng cách này:

const Chalk = require('@nasc/chalk');

const chalk = new Chalk.constructor({
  wrapper: {
    pre: '\1',
    post: '\2',
  }
});
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.