【问题标题】:Linux cat inline file with special characters带有特殊字符的 Linux cat 内联文件
【发布时间】:2017-11-06 15:20:29
【问题描述】:

我有以下脚本:

#!/bin/bash
cat << EOF
A^@B^AC^B
EOF

地点:

  • '^@' = 十进制值 0
  • '^A' = 十进制值 1
  • '^B' = 十进制值 2

所以,文件看起来像这样:

xxd main.sh
00000000: 2321 2f62 696e 2f62 6173 680a 0a63 6174  #!/bin/bash..cat
00000010: 203c 3c20 454f 460a 4100 4201 4302 0a45   << EOF.A.B.C..E
00000020: 4f46 0a                                  OF.

当我运行脚本时,十进制值 0 和 1 似乎消失了:

./main.sh | xxd
00000000: 4142 4302 0a                             ABC..

我的问题是为什么?我期待有这样的输出:

字符“A”,后接十进制值 0,后接“B”,后接十进制值 1,后接“C”,后接十进制值 2。

【问题讨论】:

    标签: linux cat


    【解决方案1】:

    原因似乎有两个。

    首先,请注意您必须在here-document引用单词/delimiter 以避免扩展

    如果word不加引号,则here-document的所有行都经过参数扩展、命令替换和算术扩展,字符序列\newline被忽略,必须使用'\'引用字符 '\'、'$' 和 '`'。

    所以,如果你这样写:

    #!/bin/bash
    cat <<"EOF"
    A^@B^AC^B
    EOF
    

    您将保留除 NULL (\0) 以外的所有字符。

    但是你不能在任何一个变量中使用 NULL char,或者 命令行参数(参见this answer)。

    可以在管道/文件中使用 NULL,因此您可能希望对 here-document 的内容进行编码并即时解码(例如使用xxd)。

    【讨论】:

    • 谢谢,我想我必须使用echo -e 而不是cat 来包含空字符。
    • 你也可以(可能更好)使用printf(例如printf '\0\01\xCA\xFE' | hd)。如果您使用echo,请务必同时添加-n
    【解决方案2】:

    在对这个问题进行了更多思考之后,我意识到引用单词/分隔符(如另一个答案所建议的)不应该影响脚本的输出(参数扩展、命令替换和算术扩展在我的脚本)。

    所以,\000 确实消失了,因为您不能在任一变量或命令行参数中使用 NULL 字符。

    但是,\001 因 bash 错误而消失。该值在 bash 内部用作转义字符。该错误出现在函数expand_word_internal 中,该函数无法正确处理转义字符(请参阅错误报告here)。

    这个 bug 已经在 bash devel 分支中修复了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      • 1970-01-01
      • 2014-05-27
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      相关资源
      最近更新 更多