bash 附加命令和输出文件中的字符转义双引号

问题描述 投票:0回答:1

我在 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

我已经尝试过但到目前为止未能通过

弥补这一点

效果最好的是

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)来“运行并存储最后一个命令”(而不是报告所有内容,然后手动删除大部分会话)

我不感兴趣的(因为我跨操作系统工作并且不能保证其他人的安装/环境)

  • Jupyter Notebook 有一个 Bash 内核,我可以使用它,然后手动复制/粘贴到文本文件中
  • Bash 是跨操作系统最常见的脚本语言,因此虽然我喜欢 Python 并且
    ipython
    会非常接近我的要求,但我的家人不能保证安装 Python,所以这是不行的。
  • 当涉及双引号时,建议进行错误处理以手动存储命令+输出;我现在有这个,只是上面的文章没有出现
  • 需要用单引号编写原始查询并进行单引号转义,然后使用
    "!!"
    而不删除双引号。这在很多地方都有效(虽然我很恼火)但单引号转义会导致使用 Salesforce 的 CLI 出现问题。

我查看了 Stack Overflow 的推荐问题,但认为他们没有回答:

bash shell printf escaping echo
1个回答
0
投票

!!
本身并不吞咽任何引号。当 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 …
,等等

© www.soinside.com 2019 - 2024. All rights reserved.