【问题标题】:bash print escaped file contentsbash 打印转义的文件内容
【发布时间】:2016-11-11 10:04:52
【问题描述】:

我正在尝试使用转义的双引号打印文件内容。

# read file contents from ${filename}
# - escape double quotes
# - represent newlines as '\n' 
# print the result
echo "my file contents: \"${out}\""

例如,如果我的文件是

<empty line>
console.log("hello, world");
<empty line>

应该打印出来

my file contents: "\nconsole.log(\"hello, world\");\n"

我尝试将 printf 与 %q 格式说明符一起使用,但遇到了删除尾随空格的问题。

【问题讨论】:

  • 哇,这真是一个不寻常的壮举。做什么的? [如果你愿意,我可以为它制作一个 C 程序]
  • 显示 如何 你在尝试printf %q -- 我向你保证,它本身并不会删除尾随空格。另一方面,如果您在命令替换中运行它(或以这种方式运行cat),则...
  • 另外,其他人也有权利——如果你想生成 JSON,请使用专为这项工作构建的工具。
  • @PaulStelian 我也可以在 C 语言中做到这一点;)我想要一个简短的脚本来做到这一点
  • @PetrPetrov,这是真的,因为$(cat file) 本身会删除尾随的换行符。相反,请尝试:IFS= read -r -d '' content &lt;file; printf '%q\n' "$content"

标签: bash printf cat


【解决方案1】:

命令替换去除尾随换行符。您可以通过添加一个虚拟的非换行符然后剥离它来防止这种情况:

printf '\n\nfoo\n\n' > file

contents="$(cat "file"; printf x)"
contents="${contents%x}"

printf "The shell equivalent of the file contents is: %q\n" "$contents"

如果您尝试生成 JSON,则应改为使用 jq

【讨论】:

  • 我也知道使用IFS= read -r -d '' contents &lt;file;假设没有 NUL——而且,如果它有它们,它无论如何都不能存储在 shell 变量中——这可行,尽管缺点是来自read 的退出状态为非零。
【解决方案2】:

只做你明确要求的两个文字转换:

IFS= read -r -d '' content <file
content=${content//'"'/'\"'/}
content=${content//$'\n'/'\n'}
echo "file contents: $content"

也就是说,如果您尝试将任意内容表示为 JSON 字符串,则让完全兼容的 JSON 解析器/生成器来完成繁重的工作:

IFS= read -r -d '' content <file
echo "file contents: $(jq -n --arg content "$content" '$content')"

...或者,甚至更好(支持包含 bash 无法存储为字符串的内容的文件),让 jq 直接从输入文件中读取:

echo "file contents: $(jq -Rs . <file)"

【讨论】:

    【解决方案3】:

    在我看来,将任意多行文本转换为 printf 格式的最可靠方法是使用 bash 内置的 printf。

    $ nl -ba testfile
         1
         2  console.log("hello, world");
         3
    $ s="$(printf '%q' "$(cat testfile; printf x)")"
    $ s="${s%x\'}"; s="${s#\$\'}"
    $ echo "$s"
    \nconsole.log("hello, world");\n\n
    

    这具有处理所有个字符的优点,包括CR和制表符,而不仅仅是换行符。

    请注意我们使用的有趣的命令扩展解决方法,以避免去除尾随的换行符。 (否则,我们只能s="$(printf '%q' "$(&lt;testfile)")"。)

    还要注意我们在echo 之前的行中所做的参数扩展。这是必需的,因为 bash 处理 %q 格式字符的方式,返回一个格式引用的字符串,而不仅仅是格式化的字符串。

    【讨论】:

    • 鉴于console.log() 是 JavaScript 源代码,OP 所需的输出实际上很可能是 JavaScript 字符串。 printf %q 可能适用于这个 today (并不是说我在没有分析的情况下断言这是真的),但不能保证它在未来会适用——如果 bash 引入了一个新的明天扩展报价表,printf %q 将在规范范围内使用该扩展报价表。
    猜你喜欢
    • 2017-01-28
    • 2012-06-12
    • 1970-01-01
    • 2021-03-01
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多