当前位置:  开发笔记 > 编程语言 > 正文

Echo扩展了PS1

如何解决《Echo扩展了PS1》经验,为你挑选了3个好方法。

我有一个shell脚本,在几个目录(fgit)中运行相同的命令.对于每个目录,我希望它显示当前提示+将在那里运行的命令.如何获得与解码(扩展)对应的字符串PS1?例如,我的默认PS1是

${debian_chroot:+($debian_chroot)}\[\e[1;32m\]\u\[\e[0m\]@\[\e[1;32m\]\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]$(__git_ps1 ' (%s)')$

我想回应最终的提示username@hostname:/path$,最好(但不一定)用漂亮的颜色.粗略地看一下Bash手册没有透露任何明确的答案,echo -e $PS1只评估颜色.



1> gniourf_gnio..:

从Bash 4.4开始,您可以使用@P扩展:

首先,我将你的提示字符串放在一个变量中myprompt使用read -r和引用的here-doc:

read -r myprompt <<'EOF'
${debian_chroot:+($debian_chroot)}\[\e[1;32m\]\u\[\e[0m\]@\[\e[1;32m\]\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]$(__git_ps1 ' (%s)')$ 
EOF

要打印提示符(如果它被解释PS1),请使用扩展${myprompt@P}:

$ printf '%s\n' "${myprompt@P}"
gniourf@rainbow:~$
$

(实际上有一些\001\002字符,来自\[\]你在这里看不到,但如果你试图编辑这篇文章,你可以看到它们;如果你输入命令,你也会在你的终端中看到它们).


为了摆脱这些,Dennis Williamson在bash邮件列表上发送的技巧是使用read -e -p这些字符由readline库解释:

read -e -p "${myprompt@P}"

这将提示用户,并myprompt正确解释.

这个帖子中,Greg Wooledge回答,你可能也只是剥离\001\002从字符串.这可以这样实现:

myprompt=${myprompt@P}
printf '%s\n' "${myprompt//[$'\001'$'\002']}"

对于这篇文章,Chet Ramey回答说你也可以完全关闭行编辑set +o emacs +o vi.所以这也会这样做:

( set +o emacs +o vi; printf '%s\n' "${myprompt@P}" )



2> paxdiablo..:

开源软件的一大优势是源是开放的:-)

Bash本身不提供此功能,但您可以使用各种技巧来提供子集(例如替换\u$USER等等).但是,这需要大量的功能重复,并确保代码与bash将来的任何内容保持同步.

如果你想获得提示变量的所有功能(并且你不介意用一些编码来弄脏你的手(如果你介意的话,为什么你在这里?)),它很容易添加到壳本身.

如果您下载代码bash(我正在查看版本4.2),则有一个y.tab.c包含该decode_prompt_string()功能的文件:

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

这是评估PSx提示变量的函数.为了允许将此功能提供给shell本身的用户(而不是仅 shell使用),您可以按照以下步骤添加内部命令evalps1.

首先,进行更改,support/mkversion.sh以免您将其与"真实"混淆bash,以便FSF可以为保修目的拒绝所有知识:-)只需更改一行(我添加了-pax位):

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

其次,更改builtins/Makefile.in添加新的源文件.这需要许多步骤.

(a)$(srcdir)/evalps1.def加到最后DEFSRC.

(b)添加evalps1.o到最后OFILES.

(c)添加所需的依赖项:

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

第三,添加builtins/evalps1.def文件本身,这是运行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 .

$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 
#include "../bashtypes.h"
#include 
#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;
}

其中exit.def很大一部分是GPL许可证(因为我修改了它),最后用一个非常简单的函数来获取和解码PS1.

最后,只需在顶级目录中构建东西:

./configure
make

bash出现的可执行文件可以重命名为paxsh,但我怀疑它会变得像它的祖先一样普遍:-)

运行它,你可以看到它在行动:

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 

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

当您将其中一个PSx变量放入提示符时,echoing $PS1只会为您提供变量,而evalps1命令会对其进行求值并输出结果.

现在,授予,对代码进行更改以bash添加内部命令可能会被一些人认为是过度的,但是,如果你想要一个完美的评估PS1,那肯定是一个选择.



3> Paused until..:

你为什么不$PS1亲自处理逃逸换人?一系列的替换如下:

p="${PS1//\\u/$USER}"; p="${p//\\h/$HOSTNAME}"

顺便说一下,zsh有能力解释提示转义.

print -P '%n@%m %d'

要么

p=${(%%)PS1}

推荐阅读
跟我搞对象吧
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有