[英]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.