Почему ошибка "недопустимый символ: ^ M"? - PullRequest
0 голосов
/ 17 апреля 2010

У меня какая-то проблема с форматированием, которую я не могу понять, приведенный ниже короткий пример использования Zsh. Почему?

$ values=( 300 400 )
$ echo "scale=20; $values[1]-$values[2]" | bc
(standard_in) 1: illegal character: ^M         // Why does it not print -100?
$ echo $values                                 // no ^M sign found!
300 400

Вспомогательные вопросы

  1. Почему 5E 4d 0a, то есть ^M, 13-й символ в ASCII?
  2. Почему знак окончания "0a" отображается в виде точки "."? "." в шестнадцатеричном формате "2E".

Ответы [ 4 ]

8 голосов
/ 17 апреля 2010

Unix и Windows имеют разные форматы окончания строки. В мире Unix строки заканчиваются символом перевода строки (LF, ascii char 10). В Windows строки заканчиваются символом возврата каретки (CR, ascii char 13), за которым следует перевод строки.

Файлы с окончаниями строк Windows должны быть преобразованы в формат Unix, прежде чем они смогут работать с инструментами Unix. В противном случае такие программы, как bc, рассматривают символы CR как нежелательные и жалуются, как в вашем случае.

Чтобы преобразовать файлы в формат Unix, вы можете использовать dos2unix(1), если он установлен, или поочередно пропустить его через sed 's/^M//g' (но не вводите литерал ^ M - нажмите Ctrl + V, а затем Ctrl + M).

Так почему ^M? Ну, возврат каретки - это непечатаемый символ . У него нет печатного представления. Для удобства ваш терминал отобразит его как ^M*. Так почему же он не появился, когда вы сделали echo $values? К сожалению, обработка аргументов командной строки удаляет его, поэтому вы его не видите.

Также для вашего удобства ваш терминал позволяет печатать непечатаемых символов с помощью Ctrl + V и Ctrl + некоторые буквы. Ctrl + V и Ctrl + M создадут символ ^M, но переместите курсор влево и вправо, и вы увидите, что он пропускает все это как один символ - не , как при вводе ^ с последующим M. В то время как you видит ^M, программы командной строки видят только необработанные данные и будут видеть реальный символ возврата каретки.

Почему 5E 4d 0a, то есть ^ M, 13-й символ в ASCII?

Вы запустили hexdump на выходе echo "^M", который производит три символа: ^, M и символ перевода строки (LF). Смотрите выше, это не то же самое, что возврат каретки!

Почему знак окончания 0a отображается как.? , это 2E в DEC. Шестнадцатеричное число 5E равно 94 в DEC, 4d равно 77 в DEC.

Hexdump отображает все непечатаемые символы в виде . символов, включая символы возврата каретки и перевода строки.


* Почему именно М? Соглашение состоит в том, чтобы добавить 64 к коду ASCII. Возврат каретки - код 13 ASCII (0x0D). Добавьте 64, и вы получите 77 (0x4D) в верхнем регистре M. См. эту страницу для полного списка.

0 голосов
/ 19 сентября 2012

Ответы на вспомогательные вопросы

I.Почему 5E 4d 0a, то есть ^ M, 13-й символ в ASCII?

Новая строка - 0a, см. Пример, предоставленный ZyX ниже.RJH разъяснил кое-что о 13-м символе. "echo -n не позволяет эхо добавлять новую строку в конце своего вывода" .Я использую Debian.

$ echo "scale=20; $values[1]-$values[2]" | hexdump -C
00000000  73 63 61 6c 65 3d 32 30  3b 20 5b 31 5d 2d 5b 32  |scale=20; [1]-[2|
00000010  5d 0a                                             |].|
00000012
xyz@xyz:~$ echo -n "scale=20; $values[1]-$values[2]" | hexdump -C
00000000  73 63 61 6c 65 3d 32 30  3b 20 5b 31 5d 2d 5b 32  |scale=20; [1]-[2|
00000010  5d                                                |]|
00000011

II.Почему знак окончания "0a" отображается в виде точки "."?"."в шестнадцатеричном формате "2E"Пожалуйста, прокомментируйте, ответьте или отредактируйте.

Информация, чтобы помочь с примерами

ASCII в HEX

`.` is `2E` in Hex
`5E` is `^` in Hex 
`4d` is `M` in Hex

Hex для ASCII: используйте это, чтобы увидеть, что означают Hex-вещи

$ echo "^M" | hexdump -C
00000000  5e 4d 0a                                          |^M.|
00000003
$ ascii -x              
    0 NUL    10 DLE    20      30 0    40 @    50 P    60 `    70 p 
    1 SOH    11 DC1    21 !    31 1    41 A    51 Q    61 a    71 q 
    2 STX    12 DC2    22 "    32 2    42 B    52 R    62 b    72 r 
    3 ETX    13 DC3    23 #    33 3    43 C    53 S    63 c    73 s 
    4 EOT    14 DC4    24 $    34 4    44 D    54 T    64 d    74 t 
    5 ENQ    15 NAK    25 %    35 5    45 E    55 U    65 e    75 u 
    6 ACK    16 SYN    26 &    36 6    46 F    56 V    66 f    76 v 
    7 BEL    17 ETB    27 '    37 7    47 G    57 W    67 g    77 w 
    8 BS     18 CAN    28 (    38 8    48 H    58 X    68 h    78 x 
    9 HT     19 EM     29 )    39 9    49 I    59 Y    69 i    79 y 
    A LF     1A SUB    2A *    3A :    4A J    5A Z    6A j    7A z 
    B VT     1B ESC    2B +    3B ;    4B K    5B [    6B k    7B { 
    C FF     1C FS     2C ,    3C <    4C L    5C \    6C l    7C | 
    D CR     1D GS     2D -    3D =    4D M    5D ]    6D m    7D } 
    E SO     1E RS     2E .    3E >    4E N    5E ^    6E n    7E ~ 
    F SI     1F US     2F /    3F ?    4F O    5F _    6F o    7F DEL
0 голосов
/ 17 апреля 2010

Возможно, вам повезет больше, если вы запустите свой файл через dos2unix, если эта программа доступна в вашей системе.

Помимо прочего, dos2unix преобразует окончания строк Windows \ r \ n в окончания строк \ n в стиле Unix.

0 голосов
/ 17 апреля 2010

^ M в одном символе - Возврат каретки - это DOS / Windows или ASCII 13 символов. Кажется, что вы каким-то образом скомпрометировали свой ввод, возможно, вставив что-то из файла Windows или что-то в этом роде ...

...