我知道CR LF(\ r \ n)将被解释为两个字符,即“回车” +“换行”,但是当它例如源代码时,这将如何影响不同的程序?
答案 0 :(得分:3)
由于它是一系列空格字符,因此CRLF在C语言中会被忽略,但在Bash中不会被忽略:
如果bash脚本(#!/bin/bash
)的第一行具有CRLF行终止符,则该脚本将无法运行。它将寻找文件/bin/bash\r
,该文件不存在。
如果脚本的其他任何行上都有CRLF行终止符,则将找不到该行上的命令(因为bash正在寻找名为some_command\r
的命令),或者将传递给{ {1}}在其最后一个参数的末尾。
答案 1 :(得分:1)
默认情况下,shell不会将CR视为空白。
带有crlf67.sh
标记的CR的源代码(^M
):
#!/bin/sh^M
^M
echo "Hello^M
World!"^M
显式运行命令:
$ sh crlf67.sh
: command not found
Hello
World!
$ sh crlf67.sh 2>&1 | vis -r
crlf67.sh: line 2: ^M: command not found
Hello^M
World!^M
$
({vis
命令是vis
程序的扩展版本,从
Brian W Kernighan,Rob Pike
The Unix Programming Environment(1983年11月)。它使非打印字符可见。)
如果使脚本可执行:
$ make crlf67
cat crlf67.sh >crlf67
chmod a+x crlf67
$ crlf67
-bash: ./crlf67: /bin/sh^M: bad interpreter: No such file or directory
$
内核也不会将CR视为空白,并且无法找到命令。
在C源代码中,正式地说,如果行尾为CRLF,则不能使用反斜杠在C中继续行,因为反斜杠后面的字符不是换行符(NL或LF);这是CR。在一行的最后一个反斜杠之后,某些编译器会忽略空格(至少是CR),GCC 9.1.0表示的是一个空格,但也包括较早的版本。它会在反斜杠后警告空格(除非您像我一样使用-Werror
;否则会出错)。这不是标准规定的内容;但是,即使-pedantic
也不会忽略错误的表示法而停止它。
源代码(crlf19.c
),CR用^M
标记,换行符用^J
标记:
#include <stdio.h>^M^J
^M^J
int main(void)^M^J
{^M^J
printf("Hello\ ^M^J
world!\ ^M^J
\n");^M^J
return 0;^M^J
}^M^J
GCC 9.1.0在macOS 10.14.5 Mojave上进行的编译:
$ gcc -O3 -g -std=c11 -Wall -Wextra -pedantic crlf19.c -o crlf19
crlf19.c: In function ‘main’:
crlf19.c:5:18: warning: backslash and newline separated by space
5 | printf("Hello\
|
crlf19.c:6:8: warning: backslash and newline separated by space
6 | world!\
|
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror crlf19.c -o crlf19
crlf19.c: In function ‘main’:
crlf19.c:5:18: error: backslash and newline separated by space [-Werror]
5 | printf("Hello\
|
crlf19.c:6:8: error: backslash and newline separated by space [-Werror]
6 | world!\
|
cc1: all warnings being treated as errors
$
此行为至少可以追溯到GCC 4.1.2 -该版本已在前Diluvian RHEL 5盒上进行了测试。
如果您在反斜杠后删除空格,仅留下CRLF行尾,那么GCC根本不会抱怨。
答案 2 :(得分:0)
这取决于正在处理文件的程序。我不相信有任何一般规则。
例如,我刚刚在原本为空的目录中创建了几个Shell脚本。其中一个名为some_command
,文件名的最后一个字符为ASCII CR。
我可以通过将CR作为命令名的一部分从Shell脚本中调用该命令。外壳程序(sh,bash或ksh)不会将CR字符视为空格。
$ ls -l
total 16
-rwxr-xr-x 1 kst kst 26 Jul 1 16:46 crlf.bash
-rwxr-xr-x 1 kst kst 25 Jul 1 16:46 crlf.ksh
-rwxr-xr-x 1 kst kst 24 Jul 1 16:46 crlf.sh
-rwxr-xr-x 1 kst kst 21 Jul 1 16:49 'some_command'$'\r'
$ cat -v crlf.bash
#!/bin/bash
some_command^M
$ cat -v crlf.ksh
#!/bin/ksh
some_command^M
$ cat -v crlf.sh
#!/bin/sh
some_command^M
$ cat -v some_command
#!/bin/sh
echo hello
$ ./crlf.bash
Hello
$ ./crlf.ksh
Hello
$ ./crlf.sh
Hello
$
我正在使用的ls
版本(GNU coreutils 8.28)具有特殊的语法,用于显示包含特殊字符的文件名。 cat -v
将CR字符显示为^M
。