Bash'here document'字/分隔符未加引号

时间:2018-03-30 22:53:34

标签: linux bash

我有以下脚本:

#!/bin/bash
cat << EOF
^A^B^C
EOF

其中:

  • '^ A'=十进制值1
  • '^ B'=十进制值2
  • '^ C'=十进制值3

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

xxd main.sh 
00000000: 2321 2f62 696e 2f62 6173 680a 6361 7420  #!/bin/bash.cat 
00000010: 3c3c 2045 4f46 0a01 0203 0a45 4f46 0a    << EOF.....EOF.

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

./main.sh | xxd
00000000: 0203 0a                                  ...

我必须引用十进制值1的单词/分隔符(cat << "EOF")来显示,但我不明白为什么。

从bash参考手册中,这是word未加引号时发生的情况:

  

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

我的问题是:

为什么在未引用单词/分隔符时,十进制值1会消失?参数扩展,命令替换和算术扩展如何影响这个?

1 个答案:

答案 0 :(得分:2)

正如评论中所指出的,我认为这也是一个错误。

在我的例子中,Bash最终将here文档文本转换为文件,同时这样做,它将here文档文本转换为某种内部字符串(istring)。这是我执行的回溯:

#0  expand_word_internal (word=0x7fffffffd610, quoted=2, isexp=0, contains_dollar_at=0x0, expanded_something=0x0) at subst.c:9155
#1  0x00005555555c1bb9 in call_expand_word_internal (w=0x7fffffffd610, q=2, i=0, c=0x0, e=0x0) at subst.c:3614
#2  0x00005555555c1cb3 in expand_string_internal (string=0x5555558a6b28 "\001\002\003\n", quoted=2) at subst.c:3649
#3  0x00005555555c2088 in expand_string_leave_quoted (string=0x5555558a6b28 "\001\002\003\n", quoted=2) at subst.c:3777
#4  0x00005555555c2197 in expand_string (string=0x5555558a6b28 "\001\002\003\n", quoted=2) at subst.c:3825
#5  0x00005555555f203b in write_here_document (fd=3, redirectee=0x5555558a6b08) at redir.c:394
#6  0x00005555555f227f in here_document_to_fd (redirectee=0x5555558a6b08, ri=r_reading_until) at redir.c:476
#7  0x00005555555f2f8b in do_redirection_internal (redirect=0x5555558a6b48, flags=1) at redir.c:970
#8  0x00005555555f1cba in do_redirections (list=0x5555558a6b48, flags=1) at redir.c:234
#9  0x00005555555a347d in execute_disk_command (words=0x5555558a5b08, redirects=0x5555558a6b48, command_line=0x5555558a5408 "cat  <<    EOF\n\001\002\003\nEOF\n", pipe_in=-1, pipe_out=-1, async=0,
    fds_to_close=0x5555558a6b88, cmdflags=0) at execute_cmd.c:5212
#10 0x00005555555a1ced in execute_simple_command (simple_command=0x5555558a6ac8, pipe_in=-1, pipe_out=-1, async=0,     fds_to_close=0x5555558a6b88) at execute_cmd.c:4386
#11 0x000055555559b098 in execute_command_internal (command=0x5555558a6a88, asynchronous=0, pipe_in=-1, pipe_out=-1,     fds_to_close=0x5555558a6b88) at execute_cmd.c:802
#12 0x000055555559a6a6 in execute_command (command=0x5555558a6a88) at execute_cmd.c:405
#13 0x00005555555841ff in reader_loop () at eval.c:180
#14 0x0000555555581bc3 in main (argc=2, argv=0x7fffffffdb68, env=0x7fffffffdb80) at shell.c:792

expand_word_internal将我的字符串从"\001\002\003"转换为其内部字符串表示形式“\001\002\001\003\"而不是"\001\001\001\002\001\003”,我认为这是所期望的行为。