Ký tự '^ M' ở cuối dòng


99

Khi tôi chạy một tập lệnh SQL cụ thể trong môi trường Unix, tôi thấy ký tự '^ M' ở cuối mỗi dòng của tập lệnh SQL khi nó được lặp lại với dòng lệnh. Tôi không biết tập lệnh SQL ban đầu được tạo trên hệ điều hành nào.

Điều gì đang gây ra điều này và làm thế nào để tôi sửa chữa nó?

Câu trả lời:


79

Nó gây ra bởi các ký tự kết thúc dòng DOS / Windows. Giống như Andy Whitfield đã nói, lệnh dos2unix của Unix sẽ giúp khắc phục sự cố. Nếu bạn muốn biết thêm thông tin, bạn có thể đọc các trang hướng dẫn cho lệnh đó.


3
Trên một số hệ thống (ví dụ Ubuntu) tên của lệnh này là "fromdos"
bobwienholt

6
Bạn có thể tải công cụ này trên OSX rất dễ dàng brew install dos2unixkhi bạn đã cài đặt homebrew
philipp

73

Sửa phần cuối dòng vibằng cách chạy như sau:

:set fileformat=unix

:w


2
Đây là một câu trả lời tuyệt vời. Cảm ơn nhiều. (lưu cài đặt dos2unix, một công cụ tôi có thể chỉ sử dụng một lần)
Jamsi

3
điều này không loại bỏ các ^Ms vì một số lý do. tập tin tham khảo: /etc/timidity/fluidr3_gm.cfg.
phil294

39

Nguyên nhân là do sự khác biệt giữa cách hệ điều hành dựa trên Windows và hệ điều hành dựa trên Unix lưu trữ các điểm đánh dấu cuối dòng.

Hệ điều hành dựa trên Windows, nhờ di sản DOS của chúng, lưu trữ cuối dòng dưới dạng một cặp ký tự - 0x0D0A( ký tự xuống dòng + nguồn cấp dữ liệu dòng). Hệ điều hành dựa trên Unix chỉ sử dụng 0x0A( nguồn cấp dữ liệu dòng ). Các ^Mbạn đang nhìn thấy là một hình ảnh của 0x0D(một trở về vận chuyển ).

dos2unix sẽ giúp bạn điều này. Bạn cũng có thể cần điều chỉnh nguồn của các tập lệnh để 'Thân thiện với Unix'.


Tôi sẽ không nói rằng các phiên bản Windows hiện tại có bất kỳ loại di sản DOS nào . Tuy nhiên, chúng vẫn có những hạn chế về khả năng tương thích.
Joey

Đây là cách dễ dàng, bạn làm một công cụ chuyển đổi tự động. Thank's
Pjl

Nhưng tại sao ^M? Tại sao lại là '^'? Tại sao lại là 'M'?
1737973

Bởi vì nó là một "nhân vật điều khiển". "^" là đại diện trực quan của việc nhấp vào phím điều khiển. Bên dưới các byte cụ thể của nó, dấu ^ là cách trình soạn thảo đại diện cho chúng.
Hejazzman

24

Cách đơn giản nhất là sử dụng vi. Tôi biết điều đó nghe có vẻ khủng khiếp nhưng nó đơn giản và đã được cài đặt trên hầu hết các môi trường UNIX. ^ M là một dòng mới từ môi trường Windows / DOS.

từ dấu nhắc lệnh: $ vi filename

Sau đó nhấn " :" để chuyển đến chế độ lệnh.

Tìm kiếm và Thay thế tất cả Trên toàn cầu là :%s/^M//g" Nhấn và giữ điều khiển rồi nhấn V rồi nhấn M " sẽ thay thế ^ M bằng không.

Sau đó, để viết và thoát, hãy nhập " :wq" Xong!


Làm thế nào để thay thế nó trong emacs?
herbertD

Cảm ơn! VI (M) thật tuyệt!
Ionică Bizău

3
Cảm ơn bạn đã giải thích về cách nhập ký tự ^ M! Tôi sẽ thay thế nó bằng \ r. Vì vậy, tôi đã làm:% s / ^ M / \ r / g
aharris88


10

Trong vi, làm một :%s/^M//g

Để nhận phím ^Mgiữ CTRL, hãy nhấn Vsau đó M(Cả hai trong khi giữ phím điều khiển) và phím ^Msẽ xuất hiện. Điều này sẽ tìm thấy tất cả các lần xuất hiện và thay thế chúng bằng không.


2
Để thay thế ^ M bằng ngắt dòng thân thiện với unix::%s/^M/\r/g
Gary Oak

8

Tập lệnh SQL ban đầu được tạo trên hệ điều hành Windows. Các ký tự '^ M' là kết quả của việc Windows và Unix có những ý tưởng khác nhau về những gì sẽ sử dụng cho một ký tự cuối dòng. Bạn có thể sử dụng perl tại dòng lệnh để sửa lỗi này.

perl -pie 's/\r//g' filename.txt

Chắc chắn, bạn CÓ THỂ sử dụng perl, nhưng bạn có đề xuất sử dụng perl trên dos2unix không?
Thomas Owens

2
Tôi chỉ cung cấp một giải pháp thay thế, vì bốn người đã nói sử dụng dos2unix.
Bill the Lizard,

2
Có, tôi thấy điều này hữu ích vì tôi đang ở trên một máy trạm lạc hậu, làm việc trong văn phòng có bộ phận CNTT thời tiền sử. Ngoại trừ tôi đã sử dụng một biến thể: perl -pi -e "s / \ x0D / \ n / g" file.csv
Rimian

7

^ M thường được gây ra bởi các dòng mới của nhà điều hành Windows và được dịch sang Unix trông giống như ^ M. Lệnh dos2unix sẽ loại bỏ chúng một cách độc đáo

dos2unix [tùy chọn] [-c chuyển đổi] [-o tệp ...] [-n trong tệp outfile ...]


5
C:\tmp\text>dos2unix hello.txt helloUNIX.txt

Sed thậm chí còn có sẵn rộng rãi hơn và cũng có thể làm được điều này nếu dos2unix không được cài đặt

C:\tmp\text>sed s/\r// hello.txt > helloUNIX.txt  

Bạn cũng có thể thử tr:

cat hello.txt | tr -d \r > helloUNIX2.txt  

Đây là kết quả:

C:\tmp\text>dumphex hello.txt  
00000000h: 48 61 68 61 0D 0A 68 61 68 61 0D 0A 68 61 68 61 Haha..haha..haha  
00000010h: 0D 0A 0D 0A 68 61 68 61 0D 0A                   ....haha..  

C:\tmp\text>dumphex helloUNIX.txt  
00000000h: 48 61 68 61 0A 68 61 68 61 0A 68 61 68 61 0A 0A Haha.haha.haha..  
00000010h: 68 61 68 61 0A                                  haha.  

C:\tmp\text>dumphex helloUNIX2.txt  
00000000h: 48 61 68 61 0A 68 61 68 61 0A 68 61 68 61 0A 0A Haha.haha.haha..  
00000010h: 68 61 68 61 0A                                  haha.  

4

Để thay thế ^ M ký tự trong trình soạn thảo vi, hãy sử dụng bên dưới

mở tệp văn bản nói t1.txt

vi t1.txt

Vào chế độ lệnh bằng cách nhấn shift + :

sau đó nhấn các phím như đã đề cập %s/^M/\r/g

in above ^M is not (shift + 6)M instead it is (ctrl + V)(ctrl + M)

Dòng cuối cùng của bạn là những gì tôi đã thiếu trong tất cả các câu trả lời trước đó. Tôi liên tục nhận được 'không tìm thấy kết quả phù hợp nào bc Tôi đang thực hiện shift + 6, vì vậy tôi đã làm những gì mà mọi hacker sẽ làm và tránh hiểu lầm của tôi bằng giải pháp của riêng tôi: ghi lại một macro để thực hiện $ để đi đến cuối mỗi dòng và sau đó nhấn x, chỉ lặp lại macro cho số dòng trong tệp.
dámthas

3

Một thay thế cho dos2unixlệnh sẽ được sử dụng các tiện ích tiêu chuẩn như sed.

Ví dụ: dos sang unix:

sed 's/\r$//' dos.txt > unix.txt

unix để dos:

sed 's/$/\r/' unix.txt > dos.txt

1

Bạn có thể xóa ^ M khỏi tệp trực tiếp thông qua lệnh sed, ví dụ:

sed -i'.bak' s/\r//g *.*

Nếu bạn hài lòng với các thay đổi, hãy xóa các tệp .bak:

rm -v *.bak


0

od -a $file rất hữu ích để khám phá các loại câu hỏi đó trên Linux (tương tự như dumphex ở trên).


0

Trong Perl, nếu bạn không muốn đặt $ / biến và sử dụng chomp (), bạn cũng có thể thực hiện:

$var =~ /\r\n//g;

Theo quan điểm của tôi


-1

Một lệnh vi khác sẽ thực hiện: :%s/.$// Thao tác này sẽ xóa ký tự cuối cùng của mỗi dòng trong tệp. Hạn chế của lệnh tìm kiếm và thay thế này là nó không quan tâm đến ký tự cuối cùng là gì, vì vậy hãy cẩn thận không gọi nó hai lần.


Tại sao lại đề cập đến nó nếu bạn biết nó không đáng tin cậy?
minexew
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.