Hủy bỏ trả lại vận chuyển trong Unix


Câu trả lời:


261

Tôi sẽ giả sử bạn tự xuống dòng trung bình ( CR, "\r", 0x0d) tại đầu dòng chứ không phải chỉ một cách mù quáng trong một tập tin (bạn có thể có họ ở giữa chuỗi cho tất cả tôi biết). Chỉ sử dụng tệp thử nghiệm này CRở cuối dòng đầu tiên:

$ cat infile
hello
goodbye

$ cat infile | od -c
0000000   h   e   l   l   o  \r  \n   g   o   o   d   b   y   e  \n
0000017

dos2unix là cách để đi nếu nó được cài đặt trên hệ thống của bạn:

$ cat infile | dos2unix -U | od -c
0000000   h   e   l   l   o  \n   g   o   o   d   b   y   e  \n
0000016

Nếu vì lý do nào đó dos2unixkhông có sẵn cho bạn, thì sedsẽ làm điều đó:

$ cat infile | sed 's/\r$//' | od -c
0000000   h   e   l   l   o  \n   g   o   o   d   b   y   e  \n
0000016

Nếu vì lý do nào đó sedkhông có sẵn cho bạn, thì edsẽ làm điều đó, theo một cách phức tạp:

$ echo ',s/\r\n/\n/
> w !cat
> Q' | ed infile 2>/dev/null | od -c
0000000   h   e   l   l   o  \n   g   o   o   d   b   y   e  \n
0000016

Nếu bạn không cài đặt bất kỳ công cụ nào trong hộp của mình, bạn sẽ gặp vấn đề lớn hơn là cố gắng chuyển đổi tệp :-)


13
\rchỉ hoạt động với GNU sed, bạn có thể làm điều này:sed `echo "s/\r//"`
lapo

15
Không sedphải cũng không echonhận ra \rtrên MacOs. Trong trường hợp này chỉ printf "\r"xuất hiện để làm việc.
Steve Powell

30
Để giải thích về nhận xét của @ steve: Trên máy Mac, hãy sử dụng thông tin sau: sed "s/$(printf '\r')\$//"
mkuity0

7
Để khắc phục sự cố trên mac, bạn cũng có thể thêm tiền tố vào chuỗi sed trích dẫn đơn $như vậy: sed $'s@\r@@g' |od -c (nhưng nếu bạn thay thế bằng thì \nbạn sẽ cần phải thoát nó)
nhed

1
Tôi không chắc chắn 100%, nhưng đối với OS X, sử dụng CTRL-V + CTRL-Mthay cho \rhình như nó có thể hoạt động.

240
tr -d '\r' < infile > outfile

Xem tr (1)


4
Không tuyệt vời: 1. không hoạt động tại chỗ, 2. có thể thay thế \ r cũng không phải tại EOL (có thể hoặc không thể là những gì bạn muốn ...).
Tomasz Gandor

10
1. Hầu hết các công cụ unixy hoạt động theo cách đó và đó thường là cách an toàn nhất để xử lý mọi việc vì nếu bạn làm hỏng, bạn vẫn có bản gốc. 2. Câu hỏi như đã nêu là loại bỏ trả lại vận chuyển, không chuyển đổi kết thúc dòng. Nhưng có rất nhiều câu trả lời khác có thể phục vụ bạn tốt hơn.
Henrik Gustafsson

1
Nếu bạn trkhông hỗ trợ \rthoát, hãy thử '\015'hoặc có thể bằng chữ '^M'(trong nhiều shell trên nhiều thiết bị đầu cuối, ctrl-V ctrl-M sẽ tạo ra một ký tự ctrl-M bằng chữ).
tripleee

Vì vậy, làm thế nào để thay đổi nó khi bạn muốn outfile = infile?
Christopher

3
@donlan, phản hồi muộn nhưng bạn thường sử dụng cái gì đó như : someProg <in >out && mv out in.
paxdiablo

38

Trường cũ:

tr -d '\r' < filewithcarriagereturns > filewithoutcarriagereturns

32

Cách đơn giản nhất trên Linux là, theo ý kiến ​​khiêm tốn của tôi,

sed -i 's/\r$//g' <filename>

Các trích dẫn mạnh mẽ xung quanh toán tử thay thế 's/\r//'rất cần thiết . Không có chúng, shell sẽ diễn giải \rnhư một lối thoát + r và giảm nó xuống một đồng bằng r, và loại bỏ tất cả chữ thường r. Đó là lý do tại sao câu trả lời được đưa ra ở trên vào năm 2009 bởi Rob không hoạt động.

Và việc thêm công cụ /gsửa đổi đảm bảo rằng thậm chí nhiều cái \rsẽ bị loại bỏ, và không chỉ cái đầu tiên.



7

sed -i s/\r// <filename>hoặc somesuch; xem man sedhoặc sự giàu có của thông tin có sẵn trên web liên quan đến việc sử dụng sed.

Một điều cần chỉ ra là ý nghĩa chính xác của "vận chuyển trở lại" ở trên; nếu bạn thực sự có nghĩa là ký tự điều khiển duy nhất "trở về vận chuyển", thì mẫu ở trên là chính xác. Nếu bạn có nghĩa là, nói chung, CRLF (trả về vận chuyển và nguồn cấp dữ liệu, đó là cách thức cung cấp dòng được thực hiện trong Windows), thì có lẽ bạn muốn thay thế \r\n. Nguồn cấp dữ liệu trần (dòng mới) trong Linux / Unix là \n.


Tôi đang cố gắng sử dụng -> sed 's / \ r \ n / = /' countryNew.txt> demo.txt không hoạt động. "hổ" "sư tử."
Suvasis

Có phải chúng ta muốn nói điều đó có nghĩa là bạn đang ở trên máy Mac? Tôi đã nhận thấy Darwin sed dường như có lệnh khác nhau và bộ tính năng theo mặc định hơn hầu hết các phiên bản Linux ...
JSH

4
FYI, s/\r//dường như không loại bỏ lợi nhuận vận chuyển trên OS X, nó dường như loại bỏ rký tự thay thế. Tôi không chắc tại sao vậy. Có lẽ nó có liên quan đến cách trích dẫn chuỗi? Như một cách giải quyết, sử dụng CTRL-V + CTRL-Mthay thế \rdường như để làm việc.

6

Nếu bạn là người dùng Vi, bạn có thể mở tệp và xóa trả lại vận chuyển bằng:

:%s/\r//g

Hoặc với

:1,$ s/^M//

Lưu ý rằng bạn nên gõ ^ M bằng cách nhấn ctrl-v và sau đó ctrl-m.


2
Không tuyệt vời: nếu tệp có CR trên mỗi dòng (nghĩa là tệp DOS chính xác), vim sẽ tải nó với filetype = dos và hoàn toàn không hiển thị ^M-s. Xung quanh đây là một tấn tổ hợp phím, đó không phải là thứ mà vim được tạo ra;). Tôi chỉ cần đi sed -i, và sau đó `-e 's / \ r $ // g' để giới hạn loại bỏ đối với CR tại EOL.
Tomasz Gandor

6

Thêm một giải pháp nữa ... Bởi vì luôn có thêm một giải pháp nữa:

perl -i -pe 's/\r//' filename

Thật tuyệt vì nó đã được sử dụng và hoạt động trong mọi hương vị của unix / linux mà tôi đã làm việc cùng.


3

Một số người khác giới thiệu dos2unixvà tôi cũng khuyên bạn nên nó. Tôi chỉ cung cấp thêm chi tiết.

Nếu được cài đặt, nhảy sang bước tiếp theo. Nếu chưa được cài đặt, tôi khuyên bạn nên cài đặt nó qua yumnhư:

yum install dos2unix

Sau đó, bạn có thể sử dụng nó như:

dos2unix fileIWantToRemoveWindowsReturnsFrom.txt

2

Nếu bạn đang sử dụng HĐH (như OS X) không có dos2unixlệnh nhưng có trình thông dịch Python (phiên bản 2.5+), lệnh này tương đương với dos2unixlệnh:

python -c "import sys; import fileinput; sys.stdout.writelines(line.replace('\r', '\n') for line in fileinput.input(mode='rU'))"

Điều này xử lý cả các tệp được đặt tên trên dòng lệnh cũng như các đường ống và chuyển hướng, giống như dos2unix. Nếu bạn thêm dòng này vào tệp ~ / .bashrc (hoặc tệp hồ sơ tương đương cho các shell khác):

alias dos2unix="python -c \"import sys; import fileinput; sys.stdout.writelines(line.replace('\r', '\n') for line in fileinput.input(mode='rU'))\""

... Lần sau khi bạn đăng nhập (hoặc chạy source ~/.bashrctrong phiên hiện tại), bạn sẽ có thể sử dụng dos2unixtên trên dòng lệnh theo cách tương tự như trong các ví dụ khác.


2

Đây là điều,

%0dlà nhân vật trở về xe ngựa. Để làm cho nó tương thích với Unix. Chúng ta cần sử dụng lệnh dưới đây.

dos2unix fileName.extension fileName.extension


1

thử điều này để chuyển đổi tập tin dos thành tập tin unix:

tập tin fromdos


1

Đối với UNIX ... Tôi đã nhận thấy dos2unix loại bỏ các tiêu đề Unicode tạo thành tệp UTF-8 của tôi. Theo git bash (Windows), đoạn script sau dường như hoạt động tốt. Nó sử dụng sed. Lưu ý rằng nó chỉ loại bỏ trả về vận chuyển ở cuối dòng và bảo toàn các tiêu đề Unicode.

#!/bin/bash

inOutFile="$1"
backupFile="${inOutFile}~"
mv --verbose "$inOutFile" "$backupFile"
sed -e 's/\015$//g' <"$backupFile" >"$inOutFile"

1

Nếu bạn đang chạy một môi trường X và có một trình soạn thảo thích hợp (mã studio trực quan), thì tôi sẽ làm theo lời giới thiệu:

Visual Studio Code: Cách hiển thị kết thúc dòng

Chỉ cần đi đến góc dưới bên phải của màn hình của bạn, mã studio hình ảnh sẽ hiển thị cho bạn cả mã hóa tệp và kết thúc dòng theo sau là tệp, chỉ với một cú nhấp chuột đơn giản, bạn có thể chuyển đổi xung quanh.

Chỉ cần sử dụng mã trực quan để thay thế cho notepad ++ trên môi trường linux và bạn đã sẵn sàng sử dụng.


Hoặc sử dụng Notepad++lệnh Edit / EOL Conversion / Unix (LF)của hệ thống Windows của bạn trước khi sao chép tệp vào hệ thống Linux của bạn.
Jesse Chisholm

1

Xóa \rtrên mọi hệ thống UNIX®:

Hầu hết các giải pháp hiện có trong câu hỏi này là dành riêng cho GNU và sẽ không hoạt động trên OS X hoặc BSD; các giải pháp bên dưới sẽ hoạt động trên nhiều hệ thống UNIX khác, và trong mọi hệ vỏ, từ tcshđến sh, nhưng vẫn hoạt động ngay cả trên GNU / Linux.

Đã thử nghiệm trên OS X, OpenBSD và NetBSD tcshvà trên Debian GNU / Linux bash.


Với sed:

Trong tcshtrên OS X, sau sedđoạn có thể được sử dụng cùng với printf, như không phải sedvà cũng không echoxử lý \rtheo cách đặc biệt như GNU làm:

sed `printf 's/\r$//g'` input > output

Với tr:

Một lựa chọn khác là tr:

tr -d '\r' < input > output

Sự khác biệt giữa sedtr:

Dường như trthiếu một dòng mới ở tệp đầu vào, trong khi sedtrên OS X và NetBSD (nhưng không phải trên OpenBSD hoặc GNU / Linux) sẽ chèn một dòng mới ở cuối tập tin ngay cả khi đầu vào bị thiếu dấu \rhoặc \nở cuối tập tin


Kiểm tra:

Đây là một số thử nghiệm mẫu có thể được sử dụng để đảm bảo điều này hoạt động trên hệ thống của bạn, sử dụng printfhexdump -C; cách khác, od -ccũng có thể được sử dụng nếu hệ thống của bạn bị thiếu hexdump:

% printf 'a\r\nb\r\nc' | hexdump -C
00000000  61 0d 0a 62 0d 0a 63                              |a..b..c|
00000007
% printf 'a\r\nb\r\nc' | ( sed `printf 's/\r$//g'` /dev/stdin > /dev/stdout ) | hexdump -C
00000000  61 0a 62 0a 63 0a                                 |a.b.c.|
00000006
% printf 'a\r\nb\r\nc' | ( tr -d '\r' < /dev/stdin > /dev/stdout ) | hexdump -C
00000000  61 0a 62 0a 63                                    |a.b.c|
00000005
% 

0

Tôi đã sử dụng python cho nó, ở đây mã của tôi;

end1='/home/.../file1.txt'
end2='/home/.../file2.txt'
with open(end1, "rb") as inf:
     with open(end2, "w") as fixed:
        for line in inf:
            line = line.replace("\n", "")
            line = line.replace("\r", "")
            fixed.write(line)

0

Mặc dù đó là một bài viết cũ hơn, gần đây tôi đã gặp vấn đề tương tự. Vì tôi có tất cả các tệp để đổi tên bên trong / tmp / blah_dir / vì mỗi tệp trong thư mục này có ký tự dấu "/ r" (hiển thị "?" Ở cuối tệp), nên tôi chỉ có thể nghĩ ra cách viết kịch bản.

Tôi muốn lưu tập tin cuối cùng có cùng tên (mà không theo dõi bất kỳ ký tự nào). Với sed, vấn đề là tên tệp đầu ra mà tôi cần phải đề cập đến một cái gì đó khác (mà tôi không muốn).

Tôi đã thử các tùy chọn khác như được đề xuất ở đây (không được coi là dos2unix vì một số hạn chế) nhưng không hiệu quả.

Cuối cùng tôi đã thử với "awk", cái mà tôi đã sử dụng "\ r" làm dấu phân cách và lấy phần đầu tiên :

mẹo là:

echo ${filename}|awk -F"\r" '{print $1}'

Đoạn mã bên dưới tôi đã sử dụng (trong đó tôi có tất cả các tệp có "\ r" là ký tự ở đường dẫn / tmp / blah_dir /) để khắc phục sự cố của tôi:

cd /tmp/blah_dir/
for i in `ls`
  do
    mv   $i     $(echo $i | awk -F"\r" '{print $1}')
done

Lưu ý: Ví dụ này không chính xác lắm mặc dù gần với những gì tôi đã làm (Đề cập ở đây chỉ để đưa ra ý tưởng tốt hơn về những gì tôi đã làm)


0

Tôi đã tạo shell-script này để xóa ký tự \ r. Nó hoạt động trong solaris và mũ đỏ:

#!/bin/ksh

LOCALPATH=/Any_PATH

for File in `ls ${LOCALPATH}`
do
   ARCACT=${LOCALPATH}/${File}
   od -bc ${ARCACT}|sed -n 'p;n'|sed 's/015/012/g'|awk '{$1=""; print $0}'|sed 's/ /\\/g'|awk '{printf $0;}'>${ARCACT}.TMP
   printf "`cat ${ARCACT}.TMP`"|sed '/^$/d'>${ARCACT}
   rm ${ARCACT}.TMP
done

exit 0

-1

bạn chỉ có thể làm điều này:

$ echo $(cat input) > output

Không biết tại sao ai đó đưa ra '-1'. Đây là một câu trả lời hoàn toàn tốt (và là câu trả lời duy nhất phù hợp với tôi).
FractalSpace

1
Ồ, xin lỗi, đó là tôi. Đợi đã, nó thực sự không hoạt động cho '\ r'!
Viacheslav Rodionov

1
@FractalSpace Đây là một ý tưởng khủng khiếp! Nó phá hủy hoàn toàn tất cả các khoảng cách trong tệp và để lại tất cả nội dung của tệp phải được giải thích bởi trình bao. Hãy thử nó với một tệp chứa một dòng a * b...
Tom Fenech
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.