Как система Linux обрабатывает CRLF в файле? - PullRequest
0 голосов
/ 01 июля 2019

Я знаю, что CR LF (\ r \ n) будет интерпретироваться как два символа, "возврат каретки" + "новая строка", но как это повлияет на разные программы, когда это, например, исходный код -

  1. Как выполнить скрипт bash?
  2. Как скомпилировать исходный код?Например, файл .c?

Ответы [ 3 ]

3 голосов
/ 01 июля 2019

Поскольку это последовательность пробельных символов, CRLF игнорируется в C, но не в Bash:

Если в первой строке скрипта bash (#!/bin/bash) есть терминатор строки CRLF, скриптне побежитОн будет искать файл /bin/bash\r, который не существует.

Если какая-либо из других строк скрипта имеет терминатор строки CRLF, команда в этой строке либо не будет найдена (так какbash ищет команду с именем some_command\r), или ей будет передано \r в конце ее последнего параметра.

1 голос
/ 02 июля 2019

Сценарий оболочки

По умолчанию оболочка не рассматривает 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 от Брайана В. Кернигана, Роба Пайка Среда программирования Unix (Ноябрь 1983). Это делает непечатные символы видимыми.)

Если вы сделаете скрипт исполняемым:

$  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

Официально в исходном коде C нельзя использовать обратную косую черту для продолжения строк в C, если конец строки - CRLF, поскольку символ после обратной косой чертыне перевод строки (NL или LF);это ЧР.Некоторые компиляторы игнорируют пробелы (по крайней мере, 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 - эта версия была протестирована на анту-дилюйском RHEL 5box.

Если вы удалите пробелы после обратной косой черты, оставив только окончания строки CRLF, GCC вообще не будет жаловаться.

0 голосов
/ 02 июля 2019

Это зависит от программы, которая обрабатывает файл.Я не верю, что есть какое-то общее правило.

Например, я просто создал несколько сценариев оболочки в пустой директории.Один из них называется some_command с ASCII CR в качестве последнего символа имени файла.

Я могу вызвать эту команду из сценария оболочки, включив этот CR в качестве части имени команды.Оболочка (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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...