简体   繁体   English

正确的zsh shell命令擒纵机构

[英]proper zsh shell command escapement

I have a pretty powerful trick I'm trying to do to save every command I ever type: 我有一个非常强大的技巧,我正在尝试保存我输入的每个命令:

function zshaddhistory() {
    COMMAND_STR=${1%%$'\n'}
    [[ ( -z $COMMAND_STR ) || ( $COMMAND_STR =~ hist(ory)? ) || \
        ( $COMMAND_STR =~ ^l(s\|l\|a)?$ ) || \
        ( $COMMAND_STR =~ ^(d\|gd\|git\ diff\|glp\|gg)$ ) \
    ]] && return 1
    # do not do anything on common commands

    # do the needful
    echo "$PWD; $COMMAND_STR; $TTY@$HOST@$(date +%s.%N)" >> ~/.zsh_enhanced_history

    # rest is supposedly "default" zshaddhistory() (except it ain't)
    print -Sr ${COMMAND_STR}
    fc -p
}

It's been quite a struggle getting this to work right (eg using print -S so it won't screw up !$ et. al.), but it's mostly working right for me now. 要让它正常工作是非常困难的(例如使用print -S所以它不会搞砸!$ et.al.),但它现在主要适合我。

However I am noticing some slight inconsistencies in what gets saved now that I am building a python script that pretty-prints the saved commands in colored columns. 但是,我注意到现在我正在构建一个python脚本,在彩色列中打印出已保存的命令,因此会出现一些轻微的不一致。

To illustrate: 为了显示:

% echo "\\"
\

now the ~/.zsh_enhanced_history now contains: 现在~/.zsh_enhanced_history现在包含:

/home/slu/util; echo "\"; /dev/pts/20@1376064693.136746657

So, it saves echo "\\\\" (which produces the output \\ ) as echo "\\" (which is not a well-formed command). 因此,它将echo "\\\\" (产生输出\\ )保存为echo "\\" (这不是格式良好的命令)。

Similarly, the command echo "\\n" is saved in with a literal newline so it will take up two lines in the history file. 类似地,命令echo "\\n"保存在文字换行符中,因此它将在历史文件中占用两行。 It is in fact this behavior that caused me to initially find it because my python regex would produce as many failed parses for a command as that command has newlines in it. 事实上,这种行为导致我最初找到它,因为我的python正则表达式会为命令产生尽可能多的失败解析,因为该命令中有新行。

I tried changing it so I save the output of printf "%q" "$COMMAND_STR" as $COMMAND_STR , and this does seem to tackle the newlines and maybe even the backslashes, but it makes it escape spaces and double-quotes, so it is also wrong. 我尝试更改它,所以我将printf "%q" "$COMMAND_STR"的输出保存为$COMMAND_STR ,这似乎解决了换行符,甚至可能是反斜杠,但它使它逃脱空格和双引号,所以它也是错的。

The regular ~/.zsh_history file does not suffer from this issue, it contains the command exactly as it was typed. 常规的~/.zsh_history文件不会遇到此问题,它包含的命令与输入的完全相同。

So somewhere in my zshaddhistory I am not doing the right transformations. 所以在我的zshaddhistory我没有做正确的转换。 Perhaps there is an extra shell-string-eval occurring I need to prevent. 也许我需要防止出现额外的shell-string-eval。

Need some help from the zsh experts out there!! 需要zsh专家的一些帮助!!

This example from the zsh mailing list uses print . zsh邮件列表中的此示例使用print Combining it with your function gives this: 将它与您的功能结合使用可以:

zshaddhistory () {
    # Print to the default history file with the newline stripped. 
    print -sr -- "${1%%$'\n'}"

    # Ignore common commands. 
    COMMAND_STR=${1%%$'\n'}
    [[ ( -z $COMMAND_STR ) || ( $COMMAND_STR =~ hist(ory)? ) || \
        ( $COMMAND_STR =~ ^l(s\|l\|a)?$ ) || \
        ( $COMMAND_STR =~ ^(d\|gd\|git\ diff\|glp\|gg)$ ) \
        ]] && return 1


    # Switch history contexts
    fc -p ~/.zsh_history_detail
    # Push the current line into the current history context with newline stripped and user / time appended. 
    print -sr -- "${1%%$'\n'} ### ${PWD} $(date '+%Y-%m-%d %R')"
    return 1
}

This appears to do what you want. 这似乎做你想要的。 I've tested using echo "\\\\" and echo "\\n" : 我已经使用echo "\\\\"echo "\\n"

charizard% cat ~/.zsh_history_detail                               
cat: /Users/simont/.zsh_history_detail: No such file or directory
charizard% echo "\\"                                               
\
charizard% cat ~/.zsh_history_detail                               
: 1376117319:0;echo "\\" ### /Users/simont 2013-08-10 16:18
charizard% cat "\n"      # This was an oopsie                      
cat: \n: No such file or directory
charizard% echo "\n"                                               


charizard% echo "\\"                                               
\
charizard% cat ~/.zsh_history_detail                               
: 1376117319:0;echo "\\" ### /Users/simont 2013-08-10 16:18
: 1376117334:0;cat "\n" ### /Users/simont 2013-08-10 16:18
: 1376117339:0;echo "\n" ### /Users/simont 2013-08-10 16:18
: 1376117343:0;echo "\\" ### /Users/simont 2013-08-10 16:19

I don't know what you mean by: 我不知道你的意思是:

but it makes it escape spaces and double-quotes, so it is also wrong 但它使它逃脱空格和双引号,所以它也是错误的

so I can't test for that. 所以我无法测试。

I got to the root of the problem, which is made evident by reading the zsh manpage section just a little more carefully than I did before. 我找到了问题的根源,通过阅读zsh手册页部分比我之前做的更加谨慎。

Under print : print

          -r     Ignore the escape conventions of echo.

So, the only change I had to make to my zshrc (my ~/.zshrc is symlinked to this zshrc file) was: 所以,我必须对我的zshrc进行的唯一更改(我的~/.zshrc zshrc链接到这个zshrc文件)是:

diff --git a/zshrc b/zshrc
index 5e72133..af97c35 100644
--- a/zshrc
+++ b/zshrc
@@ -68,7 +68,7 @@ function zshaddhistory() {
     # do not do anything on common commands

     # do the needful
-    echo "$PWD; $COMMAND_STR; $TTY@$HOST@$(date +%s.%N)" >> ~/.zsh_enhanced_history
+    print -r "$PWD; $COMMAND_STR; $TTY@$HOST@$(date +%s.%N)" >> ~/.zsh_enhanced_history

     # rest is "default" zshaddhistory()
     print -Sr ${COMMAND_STR}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM