ลบ carriage return ใน Unix


218

วิธีที่ง่ายที่สุดในการลบการรับคืนทั้งหมด\rออกจากไฟล์ใน Unix คืออะไร?


3
คุณกำลังพูดถึง '\ r' '\ n' หรือแค่น่ารังเกียจ '
v3

ที่เกี่ยวข้อง: grep เพื่อหาไฟล์ที่มี ^ M (Windows กลับรถ)

คำตอบ:


261

ฉันจะถือว่าคุณผลตอบแทนการขนส่งเฉลี่ย ( CR, "\r", 0x0d) ที่ปลายของเส้นมากกว่าแค่สุ่มสี่สุ่มห้าภายในแฟ้ม (คุณอาจจะมีพวกเขาในช่วงกลางของสตริงสำหรับทุกฉันรู้) การใช้ไฟล์ทดสอบนี้โดยใช้CRที่ท้ายบรรทัดแรกเท่านั้น:

$ 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 เป็นวิธีที่จะไปหากติดตั้งในระบบของคุณ:

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

หากเหตุผลบางอย่างdos2unixไม่สามารถใช้ได้สำหรับคุณแล้วsedจะทำ:

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

หากเหตุผลบางอย่างsedไม่สามารถใช้ได้กับคุณแล้วedจะทำในวิธีที่ซับซ้อน:

$ 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

หากคุณไม่ได้มีการใด ๆของเครื่องมือเหล่านั้นติดตั้งอยู่ในกล่องของคุณคุณได้มีปัญหาใหญ่กว่าพยายามที่จะแปลงไฟล์ :-)


13
\rใช้งานได้กับ GNU เท่านั้นไม่เช่นนั้นคุณสามารถทำได้:sed `echo "s/\r//"`
lapo

15
ทั้งsedมิได้echoรับรู้\rใน MacOs ในกรณีนี้printf "\r"ใช้งานได้เท่านั้น
Steve Powell

30
หากต้องการอธิบายอย่างละเอียดเกี่ยวกับความคิดเห็นของ @ steve: สำหรับ Mac ให้ใช้สิ่งต่อไปนี้: sed "s/$(printf '\r')\$//"
mklement0

7
กับปัญหาการแก้ไขใน mac คุณยังสามารถคำนำหน้าเดียวอ้าง sed สตริงด้วย$เช่นดังนั้น: sed $'s@\r@@g' |od -c ( แต่ถ้าคุณจะเข้ามาแทนที่ด้วย\nคุณจะต้องหนีมัน)
nhed

1
ฉันไม่แน่ใจ 100% แต่สำหรับ OS X การใช้CTRL-V + CTRL-Mแทน\rดูเหมือนว่าจะใช้ได้

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

ดูtr (1)


4
ไม่ดี: 1. ไม่ทำงานแทนที่ 2. สามารถแทนที่ \ r ไม่ได้อยู่ที่ EOL (ซึ่งอาจหรืออาจไม่ใช่สิ่งที่คุณต้องการ ... )
Tomasz Gandor

10
1. เครื่องมือ unixy ส่วนใหญ่ทำงานในลักษณะนั้นและโดยปกติแล้วเป็นวิธีที่ปลอดภัยที่สุดในการทำสิ่งต่าง ๆ เนื่องจากถ้าคุณทำพลาดคุณยังคงมีต้นฉบับอยู่ 2. คำถามตามที่ระบุไว้คือการลบการขึ้นบรรทัดใหม่ไม่ใช่เพื่อแปลงการสิ้นสุดบรรทัด แต่มีคำตอบอื่น ๆ อีกมากมายที่อาจตอบสนองคุณได้ดีขึ้น
Henrik Gustafsson

1
หากคุณtrไม่สนับสนุนการ\rหลบหนีลอง'\015'หรืออาจเป็นตัวอักษร'^M'(ในเชลล์จำนวนมากบนเทอร์มินัลจำนวนมาก ctrl-V ctrl-M จะสร้างตัวอักษร ctrl-M ตามตัวอักษร)
tripleee

ดังนั้นหนึ่งจะเปลี่ยนแปลงได้อย่างไรเมื่อคุณต้องการoutfile = infile?
Christopher

3
@donlan ตอบสนองปลาย someProg <in >out && mv out inแต่คุณมักจะใช้สิ่งที่ชอบ:
paxdiablo


32

วิธีที่ง่ายที่สุดบน Linux คือในความเห็นของฉัน

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

คำพูดที่แข็งแกร่งทั่วประกอบการทดแทน's/\r//'มีความจำเป็น หากไม่มีพวกมันเชลล์จะตีความ\rว่าเป็น escape + r และลดลงเป็นธรรมดาrและลบตัวเล็กrทั้งหมด นั่นเป็นเหตุผลที่คำตอบข้างต้นในปี 2009 โดยRobไม่ทำงาน

และการเพิ่ม/gตัวดัดแปลงทำให้มั่นใจได้ว่าแม้\rจะมีหลาย ๆ ตัวจะถูกลบออกและไม่เพียง แต่ตัวแรกเท่านั้น


27

มีโปรแกรมอรรถประโยชน์ที่เรียกว่าdos2unixที่มีอยู่ในหลาย ๆ ระบบและสามารถติดตั้งได้ง่ายที่สุด


6
บางครั้งมันถูกเรียกว่า fromdos (และ todos)
ไม่ระบุชื่อ

ลิงก์ไม่ทำงานโปรดไปที่http://dos2unix.sourceforge.net/แทน
RyanQuey

7

sed -i s/\r// <filename>หรือ somesuch เห็นหรือความมั่งคั่งของข้อมูลที่มีอยู่บนเว็บเกี่ยวกับการใช้man sedsed

สิ่งหนึ่งที่ชี้ให้เห็นคือความหมายที่แม่นยำของ "การคืนรถ" ข้างต้น หากคุณหมายถึงอักขระควบคุมอย่างเดียว "carriage return" ดังนั้นรูปแบบด้านบนนั้นถูกต้อง หากคุณหมายถึงโดยทั่วไปแล้ว CRLF (การขึ้นบรรทัดใหม่และการป้อนบรรทัดซึ่งเป็นวิธีการใช้งานตัวดึงข้อมูลบรรทัดใน Windows) คุณอาจต้องการเปลี่ยน\r\nแทน ฟีดเปลือยสาย (ขึ้นบรรทัดใหม่) ใน Linux / Unix \nมี


ฉันกำลังพยายามใช้ -> sed 's / \ r \ n / = /' countryNew.txt> demo.txt ซึ่งไม่ทำงาน "tiger" "Lion."
Suvasis

เราจะทำอย่างนั้นเพื่อหมายความว่าคุณอยู่ใน mac หรือไม่? ฉันได้สังเกตเห็นดาร์วิน sed ดูเหมือนว่าจะมีคำสั่งแตกต่างกันและชุดคุณลักษณะโดยค่าเริ่มต้นกว่ารุ่นลินุกซ์มากที่สุด ...
JSH

4
FYI, s/\r//ดูเหมือนจะไม่ลบ carriage return ใน OS X, ดูเหมือนว่าจะลบตัวrอักษรแทน ฉันไม่แน่ใจว่าทำไมถึงเป็นเช่นนั้น บางทีมันอาจจะเกี่ยวข้องกับการอ้างถึงสตริง? ในฐานะที่เป็นวิธีแก้ปัญหาการใช้CTRL-V + CTRL-Mในสถานที่\rดูเหมือนว่าจะทำงาน

6

หากคุณเป็นผู้ใช้ Vi คุณสามารถเปิดไฟล์และลบ carriage return ได้ด้วย:

:%s/\r//g

หรือกับ

:1,$ s/^M//

โปรดทราบว่าคุณควรพิมพ์ ^ M โดยกด ctrl-v และ ctrl-m


2
ไม่ดี: ถ้าไฟล์มี CR ในทุกบรรทัด (นั่นคือไฟล์ DOS ที่ถูกต้อง), vim จะโหลดด้วย filetype = dos และไม่แสดง^M-s เลย การได้รับสิ่งนี้คือการกดแป้นจำนวนหนึ่งซึ่งไม่ใช่สิ่งที่เป็นกลุ่มสำหรับ;) ฉันแค่ไปหาsed -iและจากนั้น `-e / \ r $ // g 'เพื่อ จำกัด การลบไปยัง CRs ที่ EOL
Tomasz Gandor

6

อีกวิธีแก้ปัญหา ... เพราะมีอีกหนึ่งเสมอ:

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

เป็นเรื่องที่ดีเพราะมันอยู่ในสถานที่และทำงานได้ในทุกรสชาติของยูนิกซ์ / ลินุกซ์ที่ฉันเคยทำงานด้วย


3

มีคนอื่นแนะนำdos2unixและฉันก็ขอแนะนำเช่นกัน ฉันแค่ให้รายละเอียดเพิ่มเติม

หากติดตั้งแล้วให้ข้ามไปยังขั้นตอนถัดไป หากยังไม่ได้ติดตั้งฉันขอแนะนำให้ติดตั้งผ่านyumเช่น:

yum install dos2unix

จากนั้นคุณสามารถใช้มันเช่น:

dos2unix fileIWantToRemoveWindowsReturnsFrom.txt

2

หากคุณใช้ระบบปฏิบัติการ (เช่น OS X) ที่ไม่มีdos2unixคำสั่ง แต่มีตัวแปล Python (เวอร์ชัน 2.5+) คำสั่งนี้จะเทียบเท่ากับdos2unixคำสั่ง:

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

dos2unixจับทั้งสองนี้ชื่อไฟล์บนบรรทัดคำสั่งเช่นเดียวกับท่อและเปลี่ยนเส้นทางเช่นเดียวกับ หากคุณเพิ่มบรรทัดนี้ในไฟล์ ~ / .bashrc ของคุณ (หรือไฟล์โปรไฟล์ที่เทียบเท่าสำหรับเชลล์อื่น ๆ ):

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

... ครั้งต่อไปที่คุณเข้าสู่ระบบ (หรือเรียกใช้source ~/.bashrcในเซสชันปัจจุบัน) คุณจะสามารถใช้dos2unixชื่อบนบรรทัดคำสั่งในลักษณะเดียวกับในตัวอย่างอื่น ๆ


2

นี่คือสิ่งที่

%0dคืออักขระการรับคืน เพื่อให้เข้ากันได้กับ Unix เราจำเป็นต้องใช้คำสั่งด้านล่าง

dos2unix fileName.extension fileName.extension



1

สำหรับ UNIX ... ฉันสังเกตเห็นว่า dos2unix นำส่วนหัว Unicode ออกจากไฟล์ของฉัน UTF-8 ภายใต้ git bash (Windows) สคริปต์ต่อไปนี้ดูเหมือนว่าจะทำงานได้ดี มันใช้ sed โปรดทราบว่าจะลบ carriage-return ที่ปลายบรรทัดและสงวนส่วนหัวของ Unicode

#!/bin/bash

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

1

หากคุณใช้สภาพแวดล้อม X และมีการแก้ไขที่เหมาะสม (รหัสสตูดิโอภาพ) จากนั้นฉันจะทำตามคำแนะนำ:

Visual Studio Code: วิธีแสดงการสิ้นสุดบรรทัด

เพียงไปที่มุมขวาล่างของหน้าจอรหัสสตูดิโอภาพจะแสดงทั้งการเข้ารหัสไฟล์และการสิ้นสุดของบรรทัดตามด้วยไฟล์เพียงแค่คลิกง่ายๆคุณก็สามารถสลับไปมาได้

เพียงใช้รหัสภาพแทนแผ่นจดบันทึก ++ บนสภาพแวดล้อม linux และคุณพร้อมแล้ว


หรือใช้Notepad++คำสั่งของไปยังEdit / EOL Conversion / Unix (LF)บนระบบ Windows ของคุณก่อนที่จะคัดลอกไฟล์ไปยังระบบ Linux ของคุณ
Jesse Chisholm

1

การลบ\rบนระบบ UNIX ใด ๆ :

โซลูชันที่มีอยู่ส่วนใหญ่ในคำถามนี้มีเฉพาะ GNU และจะไม่ทำงานบน OS X หรือ BSD โซลูชันด้านล่างควรทำงานกับระบบ UNIX อื่น ๆ อีกมากมายและในเชลล์ใด ๆ จากtcshถึงshแต่ยังคงใช้ได้แม้ใน GNU / Linux ด้วยเช่นกัน

ผ่านการทดสอบบน OS X, OpenBSD และ NetBSD ในtcshและใน Debian GNU / Linux bashใน


ด้วยsed:

ในtcshOS X sedข้อมูลโค้ดต่อไปนี้สามารถใช้ร่วมกันได้printfเนื่องจากไม่ใช้sedหรือechoจัดการ\rในลักษณะพิเศษอย่างที่ GNU ทำ:

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

ด้วยtr:

ตัวเลือกอื่นคือtr:

tr -d '\r' < input > output

ความแตกต่างระหว่างsedและtr:

มันจะปรากฏขึ้นเพื่อtrรักษาการขาดบรรทัดใหม่ที่ต่อท้ายจากอินพุตไฟล์ขณะที่sedใน OS X และ NetBSD (แต่ไม่ใช่ใน OpenBSD หรือ GNU / Linux) จะแทรกบรรทัดขึ้นบรรทัดใหม่ที่ท้ายสุดของไฟล์แม้ว่าอินพุตจะหายไปก็ตาม ต่อท้าย\rหรือ\nท้ายไฟล์


การทดสอบ:

ต่อไปนี้เป็นตัวอย่างการทดสอบที่สามารถใช้เพื่อให้แน่ใจว่าระบบของคุณใช้printfและhexdump -C; หรือod -cอาจใช้หากระบบของคุณหายไป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

ฉันใช้ไพ ธ อนมันนี่รหัสของฉัน;

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

แม้ว่าจะเป็นโพสต์ที่เก่ากว่าเมื่อเร็ว ๆ นี้ฉันเจอปัญหาเดียวกัน เนื่องจากฉันมีไฟล์ทั้งหมดที่จะเปลี่ยนชื่อภายใน / tmp / blah_dir / เนื่องจากแต่ละไฟล์ในไดเรกทอรีนี้มีอักขระ "/ r" ต่อท้าย (แสดง "?" ในตอนท้ายของไฟล์) ดังนั้นการทำแบบสคริปต์จึงเป็นสิ่งที่ฉันคิดได้เท่านั้น

ฉันต้องการบันทึกไฟล์สุดท้ายด้วยชื่อเดียวกัน (โดยไม่ต้องใส่อักขระใด ๆ ) ด้วยความใจเย็นปัญหาคือชื่อไฟล์เอาต์พุตที่ฉันต้องการพูดถึงอย่างอื่น (ซึ่งฉันไม่ต้องการ)

ฉันลองตัวเลือกอื่น ๆ ตามที่แนะนำที่นี่ (ไม่ถือว่า dos2unix เนื่องจากข้อ จำกัด บางอย่าง) แต่ใช้งานไม่ได้

ฉันลองด้วย "awk" ในที่สุดซึ่งทำงานที่ฉันใช้ "\ r" เป็นตัวคั่นและนำส่วนแรก :

เคล็ดลับคือ:

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

ตัวอย่างสคริปต์ด้านล่างฉันใช้ (ที่ฉันมีไฟล์ทั้งหมดมี "\ r" เป็นตัวอักษรต่อท้ายที่ path / tmp / blah_dir /) เพื่อแก้ไขปัญหาของฉัน:

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

หมายเหตุ:ตัวอย่างนี้ไม่แม่นยำมากแม้ว่าใกล้กับสิ่งที่ฉันทำงาน (กล่าวถึงที่นี่เพียงเพื่อให้ความคิดที่ดีขึ้นเกี่ยวกับสิ่งที่ฉันทำ)


0

ฉันสร้างเชลล์สคริปต์นี้เพื่อลบอักขระ \ r มันทำงานได้ในโซลาริสและหมวกแดง:

#!/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

คุณสามารถทำได้:

$ echo $(cat input) > output

ไม่ทราบสาเหตุที่มีคนให้ '-1' นี่เป็นคำตอบที่ดีอย่างสมบูรณ์ (และเป็นคำตอบเดียวที่เหมาะกับฉัน)
FractalSpace

1
โอ้ขอโทษฉันเอง รอดูสิมันใช้ไม่ได้กับ '\ r'!
Viacheslav Rodionov

1
@FractalSpace นี่เป็นความคิดที่แย่มาก! มันทำลายระยะห่างทั้งหมดในไฟล์อย่างสมบูรณ์และทำให้เนื้อหาทั้งหมดของไฟล์ถูกตีความโดยเชลล์ ลองกับไฟล์ที่มีหนึ่งบรรทัดa * b...
Tom Fenech
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.