2012-04-08 15 views
8

Duplicar posibles:
Echo expanded PS1bash: ¿Cómo evaluar PS1, PS2, ...?

¿Hay alguna forma de 'evaluar' PS1, PS2, etc dentro de una escritura del golpe?

Aunque, puedo usar medios alternativos para obtener todos los elementos de mi actual PS1, me gustaría poder reutilizar su definición en lugar de utilizar estos medios alternativos.

Por ejemplo,

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

que muy bien podría utilizar la columna 'medios alternativos' en mi escritura, pero yo no quiero. En mi PS1, yo, por ejemplo, uso el color azul en negrita a través de las secuencias de escape del terminal que me gustaría poder reutilizar simplemente evaluando PS1.

+0

Quizás otras personas lo sepan, pero no tengo idea de lo que estás hablando. ¿Qué está tratando de lograr? – Kurt

+0

¿Desea evaluar $ PS1, $ PS2? ¿O quieres atribuir valores a esas variables dentro de tu script? – Gangadhar

+0

Supongamos que hay una función o comando llamado 'evaluar'. ¿Cuál debería ser el resultado de 'evaluar PS1'? –

Respuesta

10

Una gran ventaja del software de código abierto es que la fuente es, así, :-) abierta

Si descarga el código para bash (estoy mirando a la versión 4.2), hay un archivo que contiene y.tab.c la función decode_prompt_string():.

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

se puede tratar de extraer que (junto con cualquier rutina de apoyo necesarios y construir un ejecutable que hizo el trabajo para usted Aunque, desde un intento superficial, esas rutinas de soporte parece ser mucho , por lo que esta puede ser una tarea difícil.


Aparte de eso, probablemente pueda "truco" bash en expandiéndolo para usted con algo como:

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

Ahora he puesto que a través de múltiples líneas para facilitar la lectura pero fue hecho en una línea.

Lo que hace es ejecutar una instancia interactiva de bash, pasando (lo que con suerte es) un comando no válido.

Como es interactivo, imprime el mensaje, de modo que tomo la primera línea con la cadena de comando y elimino esa cadena de comando. Lo que sobra debe ser el aviso.

En mi sistema, esto es lo que me sale:

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

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

pax> 

Sin embargo, esto no tiene problemas con varias líneas de avisos y en realidad le dará a su pronta regulares en lugar de la shell actual.


Si desea hacerlo correctamente, puede implicar la adición de un poco de bash sí. Estos son los pasos para agregar un comando interno evalps1.

En primer lugar, cambiar support/mkversion.sh para que no se confunda con un "verdadero" bash, y para que la FSF puede negar todo conocimiento para la garantía :-) basta con modificar una línea (añadí el bit -pax):

echo "#define DISTVERSION \"${float_dist}-pax\"" 

En segundo lugar, cambie `builtins/Makefile.in para agregar un nuevo archivo fuente. Esto implica una serie de pasos.

(a) Agregue $(srcdir)/evalps1.def hasta el final de DEFSRC.

(b) Agregue evalps1.o hasta el final de OFILES.

(c) Añadir las dependencias necesarias:

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

En tercer lugar, añadir el archivo builtins/evalps1.def sí mismo, este es el código que se ejecuta cuando se ejecuta el 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; 
} 

El grueso de eso es la licencia GPL (ya que la modifiqué de exit.def) con una función muy simple al final para obtener y decodificar PS1.

Por último, acaba de construir la cosa en el directorio de nivel superior:

./configure 
make 

El bash que aparece puede cambiar el nombre a paxsh, aunque dudo que alguna vez llegará a ser tan frecuente como su ancestro :-)

y ejecutarlo, puede verlo en acción:

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: ] 

Ahora, sentado, haciendo cambios en el código de bash para añadir una Algunos pueden considerar excesivo el comando interno pero, si desea una evaluación precisa de PS1, sin duda es una opción.

+0

¿Estás seguro de que lo has probado en tu sistema? Cuando intenté y me hice eco de $ expPS1, obtuve "bash:: comando no encontrado ..." como el valor. Tenga en cuenta también que cabezal -1 puede no funcionar cuando tiene un indicador de varias líneas. Además, estoy imprimiendo mi mensaje en color azul negrita. Esta es la razón por la que publiqué esta pregunta: me gustaría conservar mi PS1 por completo sin duplicar sus elementos en ninguna forma o forma. Fyi, mi PS1 está configurada para: '' \ [\ 033 [0; 34m \] \ u @ \ h $? \ w \ n $ \ [\ 033 [0m \] ''. Aunque definitivamente me gusta el ingenio de su solución, es muy lenta: hay una brecha de 1-2 segundos antes de ver ningún resultado. – Harry

+0

Esa es una larga lista de problemas que tienes :-) (1) Sí, lo intenté en mi sistema, ese último bit es una transcripción real. (2) Sí, 'head -1' no funcionará para avisos de líneas múltiples, tendrás que ser un poco más ingenioso para eso y probablemente requerirá conocimiento previo del recuento de líneas o preprocesamiento del conteo de 'PS1' '\ n' secciones. (3) No estoy seguro de cuál es el problema con el color, aunque es posible que deba forzar su configuración 'TERM '. (4) No puedo responder por la velocidad, eso depende de cuánto tiempo tarde en iniciar el shell. Si la segunda solución es inadecuada, es posible que tenga que mirar la primera. – paxdiablo

+0

Pero sospecho que puede ser _más_ esfuerzo, aunque al menos debería resolver esos problemas. Incluso puede escribir un script que haga cosas similares al código C para traducir un 'PS1' arbitrario. – paxdiablo