2012-04-08 18 views
8

Eventuali duplicati:
Echo expanded PS1bash: come valutare PS1, PS2, ...?

Esiste un modo per 'valutare' PS1, PS2, ecc dall'interno di uno script bash?

Anche se, posso utilizzare mezzi alternativi per ottenere tutti gli elementi del mio attuale PS1, mi piacerebbe davvero poter riutilizzare la sua definizione invece di utilizzare questi mezzi alternativi.

Per esempio,

===================================== 
PS1 element -->  Alternate means 
===================================== 
\u   -->  $USER 
\h   -->  $HOSTNAME 
\w   -->  $PWD 
... 
===================================== 

potevo benissimo utilizzare la colonna 'mezzi alternativi' nel mio script, ma io non voglio. Nel mio PS1, ad esempio, utilizzo il colore blu in grassetto tramite sequenze di escape del terminale che mi piacerebbe poter riutilizzare semplicemente valutando PS1.

+0

Forse altre persone lo sanno, ma non ho idea di cosa tu stia parlando. Cosa stai cercando di realizzare? – Kurt

+0

Vuoi valutare $ PS1, $ PS2? O vuoi attribuire valori a quelle variabili all'interno del tuo script? – Gangadhar

+0

Supponiamo che ci sia una funzione o comando chiamato 'evaluate'. Quale dovrebbe essere il risultato di 'valutare PS1'? –

risposta

10

Un grande vantaggio del software open source è che la fonte è, beh, aperto :-)

Se si scarica il codice per bash (sto guardando versione 4.2), c'è un file che contiene y.tab.c la funzione decode_prompt_string():.

char *decode_prompt_string (string) char *string; { ... } 

si può cercare di estrarre che (insieme a qualsiasi routine di supporto necessarie e costruire un eseguibile, che ha fatto il lavoro per voi Anche se, da una prova superficiale, queste routine di supporto sembrano essere molto , quindi potrebbe essere difficile.


Oltre a questo, probabilmente si può "ingannare" bash in espansione per voi con qualcosa di simile:

expPS1=$(echo xyzzyplughtwisty | bash -i 2>&1 
     | grep xyzzyplughtwisty 
     | head -1 
     | sed 's/xyzzyplughtwisty//g') 

Ora ho messo che su più righe per facilitarne la lettura, ma è stato fatto su un linea.

Ciò che fa è eseguire un'istanza interattiva di bash, passando (che si spera sia) un comando non valido.

Poiché è interattivo, stampa il prompt in modo da afferrare la prima riga con la stringa di comando su di esso e rimuovere quella stringa di comando. Ciò che rimane dovrebbe essere il prompt.

Sul mio sistema, questo è ciò che ottengo:

pax> expPS1=$(echo xyzzyplughtwisty | bash -i 2>&1 | grep xyzzyplughtwisty | head -1 | sed 's/xyzzyplughtwisty//g') 

pax> echo "[$expPS1]" 
[pax> ] 

pax> 

Tuttavia, questo ha problemi con multi-linea di prompt e sarà effettivamente dare il prompt regolare, piuttosto che quello attuale shell.


Se si desidera farlo correttamente, può comportare l'aggiunta di un po 'per bash sé. Ecco i passaggi per aggiungere un comando interno evalps1.

In primo luogo, cambiare support/mkversion.sh in modo che non si confonderlo con un "vero" bash, e in modo che la FSF può negare tutta la conoscenza ai fini della garanzia :-) semplicemente cambiare una riga (ho aggiunto il bit -pax):

In secondo luogo, modificare `builtins/Makefile.in per aggiungere un nuovo file sorgente. Ciò comporta una serie di passaggi.

(a) Aggiungere $(srcdir)/evalps1.def alla fine di DEFSRC.

(b) Aggiungere evalps1.o alla fine di OFILES.

(c) Aggiungere le dipendenze richieste:

evalps1.o: evalps1.def $(topdir)/bashtypes.h $(topdir)/config.h \ 
      $(topdir)/bashintl.h $(topdir)/shell.h common.h 

In terzo luogo, aggiungere il file builtins/evalps1.def stesso, questo è il codice che viene eseguito quando si esegue il comando evalps1:

This file is evalps1.def, from which is created evalps1.c. 
It implements the builtin "evalps1" in Bash. 

Copyright (C) 1987-2009 Free Software Foundation, Inc. 

This file is part of GNU Bash, the Bourne Again SHell. 

Bash is free software: you can redistribute it and/or modify 
it under the terms of the GNU General Public License as published by 
the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version. 

Bash is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
GNU General Public License for more details. 

You should have received a copy of the GNU General Public License 
along with Bash. If not, see <http://www.gnu.org/licenses/>. 

$PRODUCES evalps1.c 

$BUILTIN evalps1 
$FUNCTION evalps1_builtin 
$SHORT_DOC evalps1 
Outputs the fully interpreted PS1 prompt. 

Outputs the PS1 prompt, fully evaluated, for whatever nefarious purposes 
you require. 
$END 

#include <config.h> 
#include "../bashtypes.h" 
#include <stdio.h> 
#include "../bashintl.h" 
#include "../shell.h" 
#include "common.h" 

int 
evalps1_builtin (list) 
    WORD_LIST *list; 
{ 
    char *ps1 = get_string_value ("PS1"); 
    if (ps1 != 0) 
    { 
    ps1 = decode_prompt_string (ps1); 
    if (ps1 != 0) 
    { 
     printf ("%s", ps1); 
    } 
    } 
    return 0; 
} 

Il grosso di questo è la licenza GPL (poiché l'ho modificata da exit.def) con una funzione molto semplice alla fine per ottenere e decodificare PS1.

Infine, solo costruire la cosa nella directory di livello superiore:

./configure 
make 

Il bash che appare può essere rinominato paxsh, anche se dubito che sarà mai diventare così diffuso come il suo antenato :-)

E in esecuzione, è possibile vedere in azione:

pax> mv bash paxsh 

pax> ./paxsh --version 
GNU bash, version 4.2-pax.0(1)-release (i686-pc-linux-gnu) 
Copyright (C) 2011 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 

This is free software; you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. 

pax> ./paxsh 

pax> echo $BASH_VERSION 
4.2-pax.0(1)-release 

pax> echo "[$PS1]" 
[pax> ] 

pax> echo "[$(evalps1)]" 
[pax> ] 

pax> PS1="\h: " 

paxbox01: echo "[$PS1]" 
[\h: ] 

paxbox01: echo "[$(evalps1)]" 
[paxbox01: ] 

Ora, concesso, facendo modifiche al codice per bash per aggiungere un n comando interno può essere considerato eccessivo da alcuni, ma, se si desidera una valutazione accurata di PS1, è certamente un'opzione.

+0

Sei sicuro di averlo provato sul tuo sistema? Quando ho provato ed echo $ expPS1, ho ottenuto "bash:: comando non trovato ..." come valore. Nota anche che head -1 potrebbe non funzionare quando hai un prompt su più righe. Inoltre, sto stampando la mia richiesta in grassetto di colore blu. Questa è la ragione per cui ho postato questa domanda: mi piacerebbe conservare la mia PS1 completamente senza duplicare i suoi elementi in qualsiasi forma o forma. Fyi, il mio PS1 è impostato su: ''\ [\ 033 [0; 34m \] \ u @ \ h $? \ W \ n $ \ [\ 033 [0m \] ''. Mentre mi piace decisamente l'ingegnosità della tua soluzione, è molto lento: c'è un intervallo di 1-2 secondi prima di vedere qualsiasi risultato. – Harry

+0

Questa è una lista di problemi che hai :-) (1) Sì, ho provato sul mio sistema, l'ultimo bit è una trascrizione reale. (2) Sì, 'head -1' non funzionerà per i prompt multiline, dovrai essere un po 'più ingegnoso per questo e probabilmente richiederà la pre-conoscenza del conteggio delle righe o pre-elaborazione del conteggio' PS1' '\ n' sezioni. (3) Non sono sicuro di quale sia il problema con il colore, anche se potrebbe essere necessario forzare l'impostazione 'TERM'. (4) Non posso garantire per la velocità, che dipende da quanto tempo ci vuole per avviare la shell. Se la seconda soluzione è inadeguata, potrebbe essere necessario dare un'occhiata al primo. – paxdiablo

+0

Ma sospetto che possa essere _more_ effort, anche se almeno dovrebbe risolvere quei problemi. Puoi anche scrivere uno script che fa cose simili al codice C per tradurre un 'PS1 arbitrario '. – paxdiablo

Problemi correlati