Come posso ottenere lunghe righe di comando per passare alla riga successiva?


108

Qualcosa che ho notato in Ubuntu da molto tempo che mi ha frustrato è quando sto digitando un comando sulla riga di comando che diventa più lungo (più largo) della larghezza del terminale, invece di passare a una nuova riga, torna a colonna 1 sulla stessa riga e inizia a sovrascrivere l'inizio della mia riga di comando. (In realtà non sovrascrive il comando effettivo, ma visivamente, sta sovrascrivendo il testo visualizzato).

È difficile da spiegare senza vederlo, ma supponiamo che il mio terminale abbia una larghezza di 20 caratteri (il mio è più simile a 120 caratteri - ma a titolo di esempio) e voglio fare eco all'alfabeto inglese. Quello che scrivo è questo:

echo abcdefghijklmnopqrstuvwxyz

Ma come appare il mio terminale prima di premere il tasto è:

pqrstuvwxyzghijklmno

Quando premo invio, echo

abcdefghijklmnopqrstuvwxyz

quindi so che il comando è stato ricevuto correttamente. Ha appena terminato la mia digitazione dopo la "o" e ricominciato sulla stessa riga.

Quello che mi sarei aspettato che accadesse, se avessi digitato questo comando su un terminale di soli 20 caratteri sarebbe questo:

echo abcdefghijklmno
pqrstuvwxyz

Background: sto usando bash come shell e ho questa riga nel mio ~ / .bashrc:

set -o vi

per poter navigare nella riga di comando con i comandi VI. Attualmente sto usando il server Ubuntu 10.10 e mi sto collegando al server con Putty.

In qualsiasi altro ambiente in cui ho lavorato, se digito una lunga riga di comando, verrà aggiunta una nuova riga sotto la riga su cui sto lavorando quando il mio comando supera la larghezza del terminale e quando continuo a digitare posso vedere il mio comando su 2 linee diverse. Ma per tutto il tempo che ricordo di aver usato Ubuntu, i miei comandi lunghi occupano solo 1 riga.

Questo succede anche quando torno ai comandi precedenti nella cronologia (premo Esc, quindi "K" per tornare ai comandi precedenti) - quando arrivo a un comando precedente che era più lungo della larghezza del terminale, la riga di comando ottiene distrutto e non so dire dove mi trovo nel comando.

L'unica soluzione che ho trovato per vedere l'intero comando lungo è premere "Esc-V", che apre il comando corrente in un editor VI.

Non credo di avere qualcosa di strano nel mio file .bashrc. Ho commentato la riga "set -o vi" e ho ancora avuto il problema.

Ho scaricato una nuova copia di Putty e non ho apportato alcuna modifica alla configurazione: ho appena digitato il mio nome host per connettermi e ho ancora il problema, quindi non penso che sia qualcosa con Putty (a meno che non sia necessario apportare alcune modifiche alla configurazione)

Qualcun altro ha avuto questo problema e qualcuno può pensare a come risolverlo?

modificare

Era il mio file .bashrc. Ho copiato lo stesso profilo da una macchina all'altra e ho usato caratteri speciali nel mio $ PS1 che in qualche modo lo stanno gettando via. Ora sto rispettando le variabili bash standard per il mio $ PS1.

Grazie a @ ændrük per il suggerimento su .bashrc!

... Fine modifica ...


1
Solo per essere sicuro che il problema non sia causato dal tuo file .bashrc, ti consiglio di sostituirlo temporaneamente con una copia di /etc/skel/.bashrc. Tieni presente che dovrai riconnetterti per rendere effettive le modifiche e assicurati di mantenere un backup del tuo .bashrc.
ændrük,

1
Quale applicazione terminale stai usando? Il comportamento che stai descrivendo non è normale, certamente non è un valore predefinito.
João Pinto,

Nelle shell in cui ho lavorato (e nell'interfaccia della riga di comando di Cisco) puoi anche digitare Ctrl-L per visualizzare nuovamente la riga che stai digitando, anche se è fuori schermo. Nella tua situazione, ciò potrebbe comunque produrre l'output interrotto di cui stai parlando, ma sarei curioso.
belacqua,

3
Sentiti libero di creare una "risposta" che spieghi la soluzione e contrassegnala come accettata. Può sembrare un po 'sciocco, ma avere una risposta adeguata aiuta a mantenere organizzato il sito e potrebbe guidare in modo più efficace gli altri che hanno problemi simili in futuro.
ændrük,

Come da questa risposta su serverfault , usatput smam
Samveen il

Risposte:


136

Assicurati che tutti i byte non stampabili nella tua PS1 siano contenuti all'interno \[ \]. Altrimenti, bash li conterà per la lunghezza del prompt. Usa la lunghezza del prompt per determinare quando avvolgere la linea.

Ad esempio, qui bash conta il prompt come 19 colonne di larghezza, mentre il prompt visualizzato dal terminale è largo solo 10 colonne ( My promptscritto in ciano e >scritto nel colore predefinito):

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

mentre qui conta solo il prompt come 10 colonne di larghezza perché ignora i byte tra lo speciale \[e gli \]escape:

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

Per buona pratica, tuttavia, utilizzare tputper generare le uscite di terminale anziché codificarle a fondo:

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

Vedi http://mywiki.wooledge.org/BashFAQ/053 e anche http://wiki.bash-hackers.org/scripting/terminalcodes per ulteriori informazioni tput.


3
Questa è una grande spiegazione del problema che la risposta accettata non fornisce
Jamie Cook,

Nell'ultima riga di codice PS1='...': perché le virgolette singole non impediscono $cyane $resetsostituiscono?
Andrybak,

2
@andrybak, impediscono $cyane $resetvengono sostituiti, ma PS1vengono valutati ogni volta che viene stampato il prompt. Puoi vederlo provando PS1='$var> 'e poi dai varvari valori e vedi come cambia il prompt. Quindi provare PS1="$var> " e notare che il prompt rimane statico; $varsi è espanso durante il compito, non tutte le volte PS1viene valutato.
geirha,

1
Questo è fantastico Grazie mille per aver pubblicato questo! Rende molto più facile e più leggibile la fuga dalle parentesi quadre.
phyatt,

Come faccio a farlo funzionare PS1=${PS1}"\e]2;$@\a". Ho provatoPS1=${PS1}"\[\e]2;\]$@\[\a\]"
Ramana Reddy il

59

Immagino che tu abbia configurato il tuo PS1con i colori, giusto?

Assicurati solo di avere \[all'interno del PS1preventivo che precede il tuo set di colori

Per esempio:

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

La mia PS1 era export PS1='^[[96m'$(hostname)'<^[[92m${PWD}^[[96m>^[[97m '- la sto usando da molto tempo - è compatibile con KSH ...
BrianH,

2
Wow. Uso i prompt dei terminali da sempre e non ho mai avuto questo problema prima. Non l'avrei mai capito. Grazie.
bchurchill,

3
usando \ [mentre usando virgolette semplici si ottiene una barra non intenzionale. inoltre, dovrebbe essere usato] alla fine dei caratteri magici, come indicato nella risposta più votata
igorsantos07

2
-1 non funziona. Devi avvolgere la sezione non stampabile con \[all'inizio e \]alla fine.
wjandrea,

@ igorsantos07 La doppia barra rovesciata \\[era un errore di battitura causato da una modifica. L'ho risolto.
wjandrea,

11

Ho avuto un problema simile e finalmente ho trovato una soluzione semplice.

Aggiungi la seguente riga nel tuo .bashrcfile:

COLUMNS=250

Quindi digitare source ~/.bashrcper ottenere l'effetto desiderato.


In alcuni casi, come le suddivisioni di terminazione ristretta, il problema non riguarda i caratteri di colore promt ma solo un valore COLONNE errato. Questa risposta mi ha portato fuori da un buco molto fastidioso!
Carles Sala,

1
Disconnettersi non è necessario. Fare source .bashrc. Il tuo prompt si aggiornerà immediatamente
Sergiy Kolodyazhnyy il

1
Ho scoperto che dal momento che non avevo setwinsizeimpostato Shopt per il mio bash, quindi non stava aggiornando COLONNE nel modo giusto, vedi unix.stackexchange.com/a/167911/8337
rogerdpack

1
Ho export COLUMNS=250seguito export TERM=xtermed è stato felice.
Philip Kearns,

5

Ho avuto lo stesso problema con un prompt colorato personalizzato, anche se contenevo codici colore all'interno \[e \]delimitatori. Si scopre che bash ha problemi nell'eco dei colori all'interno di una funzione . Ho finito per usare solo le variabili per il mio prompt, e sebbene il mio .bashrc sia un po 'meno elegante, ora tutto funziona bene.


Se qualcuno sta ancora leggendo questo, in realtà è possibile sfuggire ai colori in una funzione. Vedi questa risposta sulla domanda collegata.
wjandrea,

3

Una cosa semplice da fare sarebbe aggiungere la seguente riga prima di impostare la PS1:

stty columns 1000

Per esempio,

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

tuttavia ciò influisce su altri comandi unix come ls e man.


1
Funziona in OSX.
Raskhadafi,

4
Questo influenza anche vim. Per favore, non usare questo.
solo il

0

Ho avuto questo problema quando connesso in tmux. Il problema era che avevo una ipythonsessione in background ( ctrl + z) e che in qualche modo interrompeva il ritorno a capo. Non appena l'ho chiuso ( fg, ctrl+d+d) il mio terminale ha iniziato a funzionare correttamente

Quindi controlla se ci sono richieste interattive interrotte.


0

Quindi ho avuto lo stesso problema con una leggera svolta e ho pensato di condividere anche la mia soluzione, solo per aggiungere la mia piccola sfumatura: D

La mia PS1 iniziale era

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

Il problema che avevo era che stavo cercando di cambiare il titolo del mio terminale e il prompt dei comandi. Il modo in cui l'ho fatto è stato aggiungendo \[\033]0;\]Title\aalla variabile PS1 .

Quindi ora la mia PS1 era:

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

Questo ha incasinato la linea per me. Alla fine ho capito che a Bash non sembra piacere avere\aAlla fine alla fine. Per aggirare questo, ho messo il titolo in una variabile, che sembrava risolverlo.

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

0

\[e \]non ha funzionato per me. Immagino che ci fosse qualcosa di diverso nel modo in cui stavo generando il prompt (da un programma esterno) o perché il mio prompt era "dinamico".

Dopo aver letto questo ho scoperto che puoi effettivamente sfuggire ai codici colore con i byte 0x01e 0x02.

ad esempio sto usando una versione speciale di Chalk e avvolgo i colori usando questo:

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

const chalk = new Chalk.constructor({
  wrapper: {
    pre: '\1',
    post: '\2',
  }
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.