我在 Bash 中使用各种诊断文件(文本 /
jq
用于 JSON / yq
用于 YAML / xpath
用于 XML,lnav
用于日志文件),我需要在报告之前动态确定有意义的数据解析最终命令及其输出。
不久前写在这里,在我通过回显 Bash 中运行的最后一个命令?发现我可以使用
!!
来运行上一个命令并将其结果存储到文件中。
我遇到的问题是一种边缘情况,当 run 命令使用双引号时,它们在隐藏时会被省略:
$ echo "hello"
hello
$ echo "!!" >> test && !! >> test
echo "echo "hello"" >> test && echo "hello" >> test
$ cat test
echo hello # no double-quotes
hello # but right answer
我已经尝试过但到目前为止未能通过
弥补这一点-e
为您提供echo
字符转义sed
printf
与 %b
或 %s
tee
""
而不是 "
script
效果最好的是
script
,除了 A)我只需要保留 <5% of commands/output ran & B) I haven't figured out to load my Dotfiles (though I assume that answer lies in man script
的 SCRIPT
或 SHELL
环境变量,如果这是最好的选择,我会进一步调查)。
当要求其他人重复我编写的查询时(例如,监控解决步骤的有效性),我的问题变得不美观且具有干扰性:
# what I would run
$ echo '["a-a","b-a"]' | jq -rc '.[]|select(.=="a-a")'
a-a
# how I would cache for others to run
$ echo "!!" >> test && !! >> test
echo "echo '["a-a","b-a"]' | jq -rc '.[]|select(.=="a-a")'" >> test && echo '["a-a","b-a"]' | jq -rc '.[]|select(.=="a-a")' >> test
# this command does not work unless !! is within double quotes which partially seems to induce the issue
# what stored to file for others to run
$ cat test
echo '[a-a,b-a]' | jq -rc '.[]|select(.==a-a)'
a-a
# command will error for others because double-quotes dropped
$ echo '[a-a,b-a]' | jq -rc '.[]|select(.==a-a)'
jq: error: a/0 is not defined at <top-level>, line 1:
.[]|select(.==a-a)
jq: error: a/0 is not defined at <top-level>, line 1:
.[]|select(.==a-a)
jq: 2 compile errors
我所期待/希望的是
echo
或printf
中有一个标志,该标志在运行时转义双引号"!!"
或避免!!
需要双引号script
(使用 Dotfiles)来“运行并存储最后一个命令”(而不是报告所有内容,然后手动删除大部分会话)我不感兴趣的(因为我跨操作系统工作并且不能保证其他人的安装/环境)
ipython
会非常接近我的要求,但我的家人不能保证安装 Python,所以这是不行的。"!!"
而不删除双引号。这在很多地方都有效(虽然我很恼火)但单引号转义会导致使用 Salesforce 的 CLI 出现问题。我查看了 Stack Overflow 的推荐问题,但认为他们没有回答:
!!
本身并不吞咽任何引号。当 shell 按字面解释替换(包括解析引用的内容)时,就会发生这种情况。 "!!"
只是用双引号括起来,这仍然有助于 shell 的解释,但现在它也很容易干扰来自上一个命令的引号。
更好的方法是通过其他方式检索最后一个命令,例如
history
。有多种方法可以过滤最后一种,以下是一些示例:
$ echo '["a-a","b-a"]' | jq -rc '.[]|select(.=="a-a")'
a-a
$ cmd="$(history -- -2 | head -1 | cut -c 8-)"
$ echo '["a-a","b-a"]' | jq -rc '.[]|select(.=="a-a")'
a-a
$ cmd="(history -w /dev/stdout | tail -n2 | head -n1)"
$ echo '["a-a","b-a"]' | jq -rc '.[]|select(.=="a-a")'
a-a
$ cmd="$(HISTTIMEFORMAT="$(echo -e '\r\e[K')" history -- -2 | head -n1)"
所有这些示例都将最后一个命令的内容分配给 shell 变量:
$ printf '%s\n' "$cmd"
echo '["a-a","b-a"]' | jq -rc '.[]|select(.=="a-a")'
或者,您也可以将其重定向到文件
cmd="$(…)"
,而不是使用分配 … > file
,将其通过管道传输到另一个处理器 … | jq …
,等等