我有一个脚本,可以从 shell 历史记录中提取一些内容并将其保存到文件中,但是如果历史记录条目中有换行符,它会以文字\n
而不是换行符返回给我。我想\n
在将其保存到文件之前将其替换为换行符。
我使用的是 OS X,并且认为问题可能是 OS X 附带的基于 BSD 的问题(当不正常运行sed
时,这似乎总是问题!),所以我尝试了,并且在首先尝试:sed
gsed
sed
gsed
history -1 | awk '{$1=""; print}' | gsed -e 's/^[[:space:]]*//' -e s/'\\n'/"\n"/
但如果可能的话,我想要一些可以与sed
Linux 或 OS X 上的默认实用程序(无论是或其他东西)一起使用的东西,因为我不能指望gsed
在 OS X 上安装,而且因为 GNUsed
是正常的sed
对于 Linux 来说显然不需要gsed
.
答案1
sed 's/\\\\/& /g;s/\\n/\
/g; s/\\\\ /\\\\/g' <in >out
...应该处理ewline 替换,而不会误解反斜杠转义 - 这样您仍然可以在输入中\n
包含文字。不过,我对如何从历史命令中\\n
获取 a 有点模糊。\n
我尝试zsh
找出如何\n
从历史文件中读出 ewline 而不会像这样转义:
echo '
\n'
history -1
11355 echo '\n\n'
那不行。所以,我尝试了这个:
hist(){ ! cat "$1"; }
echo '
\n'
FCEDIT=hist fc -1
echo '
\n'
...所以这可能就是你应该做的
由于某种原因,以不明确的方式zsh
转义了\n
ewlineshistory
或fc -l
输出,但是当它将历史命令交给某个编辑器时,它会给出真实的东西。
zsh
的主要history
操作方式是fc
,并且该history
命令只不过是 的别名fc -l
。当fc
使用该选项调用时-l
,它将列出匹配的历史记录行到标准输出(在模糊地转义任何不可打印字符之后),但是fc
的默认行为是使用一个或多个临时文件参数调用另一个实用程序,该实用程序已将其参数的所有历史匹配项写入其中。
fc
从环境变量中派生它调用的实用程序的名称$FCEDIT
,或者,如果未设置或为 null,则从 派生$EDITOR
,或者,如果同样不成功,则默认为vi
。如果调用的实用程序返回 true,则fc
随后将尝试运行它在(想必)在删除临时文件之前对其进行了编辑。
因此,上述命令序列替代cat
任何编辑器命令,并反转其返回值,以便成功读取 的fc
临时文件将返回 false - 以防止fc
再次尝试运行命令。
一个更完整的、无需调用外部实用程序的嵌入式解决方案可能如下所示:
history()
case $1 in
(*/*) ! while [ -r "$1" ]
do while read -rE RTN
do :; done <$1
shift; done;;
(*) local RTN=1 IFS=
FCEDIT=history fc "$@"
return $((RTN*$?))
esac
...它应该几乎透明地处理您可能期望zsh
的history
命令执行的任何参数列表;只是它的输出始终是文字,并且输出中从不包含历史时间戳或事件编号(除非你像这样称呼它history -l [args]
,在这种情况下它将表现为内置history
)。