ฉันจะตั้งโปรแกรมขึ้นvi
บรรทัดใหม่ของ DOS / Windows เป็น Unix โดยทางโปรแกรมได้อย่างไร(เช่นไม่ใช้)
dos2unix
และunix2dos
คำสั่งที่ไม่สามารถใช้ได้ในบางระบบ ฉันจะเลียนแบบสิ่งเหล่านี้ด้วยคำสั่งเช่นsed
/ awk
/ ได้tr
อย่างไร
ฉันจะตั้งโปรแกรมขึ้นvi
บรรทัดใหม่ของ DOS / Windows เป็น Unix โดยทางโปรแกรมได้อย่างไร(เช่นไม่ใช้)
dos2unix
และunix2dos
คำสั่งที่ไม่สามารถใช้ได้ในบางระบบ ฉันจะเลียนแบบสิ่งเหล่านี้ด้วยคำสั่งเช่นsed
/ awk
/ ได้tr
อย่างไร
คำตอบ:
คุณสามารถใช้tr
เพื่อแปลงจาก DOS เป็น Unix; อย่างไรก็ตามคุณสามารถทำได้อย่างปลอดภัยหาก CR ปรากฏในไฟล์ของคุณเป็นไบต์แรกของคู่ไบต์ CRLF เท่านั้น โดยปกติจะเป็นกรณี. จากนั้นคุณใช้:
tr -d '\015' <DOS-file >UNIX-file
โปรดทราบว่าชื่อDOS-file
จะแตกต่างจากชื่อUNIX-file
; หากคุณพยายามใช้ชื่อเดียวกันสองครั้งคุณจะพบว่าไม่มีข้อมูลในไฟล์
คุณไม่สามารถทำได้อีกทางหนึ่ง (ด้วยมาตรฐาน 'tr')
ถ้าคุณรู้ว่าวิธีการป้อนกลับรถเข้าไปในสคริปต์ ( control-V, control-Mจะเข้าสู่การควบคุม-M) แล้ว:
sed 's/^M$//' # DOS to Unix
sed 's/$/^M/' # Unix to DOS
โดยที่ '^ M' เป็นตัวควบคุม -M คุณยังสามารถใช้กลไกการbash
อ้างอิง ANSI-Cเพื่อระบุการขึ้นบรรทัดใหม่:
sed $'s/\r$//' # DOS to Unix
sed $'s/$/\r/' # Unix to DOS
อย่างไรก็ตามหากคุณจะต้องทำสิ่งนี้บ่อยครั้ง (พูดมากกว่าหนึ่งครั้งโดยประมาณ) คุณจะต้องติดตั้งโปรแกรมแปลง (เช่นdos2unix
และunix2dos
หรืออาจจะdtou
และutod
) และใช้มัน
หากคุณต้องการประมวลผลทั้งไดเรกทอรีและไดเรกทอรีย่อยคุณสามารถใช้zip
:
zip -r -ll zipfile.zip somedir/
unzip zipfile.zip
สิ่งนี้จะสร้างไฟล์เก็บถาวรซิปที่มีการสิ้นสุดบรรทัดเปลี่ยนจาก CRLF เป็น CR unzip
จากนั้นจะวางไฟล์ที่แปลงแล้วกลับเข้าที่ (และขอให้คุณส่งไฟล์เป็นไฟล์ - คุณสามารถตอบ: ใช่ไปทั้งหมด) เครดิตให้กับ @vmsnomad สำหรับการชี้เรื่องนี้
tr -d '\015' <DOS-file >UNIX-file
where DOS-file
== UNIX-file
เพียงส่งผลให้ไฟล์ว่างเปล่า ไฟล์ที่ส่งออกจะต้องเป็นไฟล์อื่นโชคไม่ดี
sed
ตัวเลือกGNU -i
(สำหรับใช้ในสถานที่) ทำงานได้ ข้อ จำกัด คือไฟล์ที่เชื่อมโยงและ symlink sort
คำสั่งมี 'เสมอ' (ตั้งแต่ปี 1979 หากไม่ได้ก่อนหน้านี้) สนับสนุน-o
ตัวเลือกซึ่งสามารถแสดงรายการหนึ่งแฟ้มใส่ อย่างไรก็ตามนั่นเป็นส่วนหนึ่งเพราะsort
ต้องอ่านอินพุตทั้งหมดก่อนจึงจะสามารถเขียนเอาต์พุตใด ๆ ได้ โปรแกรมอื่น ๆ สนับสนุนการเขียนทับไฟล์อินพุตอย่างใดอย่างหนึ่งเป็นระยะ คุณสามารถค้นหาโปรแกรมวัตถุประสงค์ทั่วไป (สคริปต์) เพื่อหลีกเลี่ยงปัญหาใน'The UNIX Programming Environment'โดย Kernighan & Pike
sed -i $'s/\r$//' filename
- เพื่อแก้ไข ฉันกำลังทำงานกับเครื่องที่ไม่สามารถเข้าถึงอินเทอร์เน็ตดังนั้นการติดตั้งซอฟต์แวร์จึงเป็นปัญหา
tr -d "\r" < file
ลองดูตัวอย่างที่นี่โดยใช้sed
:
# IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format.
sed 's/.$//' # assumes that all lines end with CR/LF
sed 's/^M$//' # in bash/tcsh, press Ctrl-V then Ctrl-M
sed 's/\x0D$//' # works on ssed, gsed 3.02.80 or higher
# IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format.
sed "s/$/`echo -e \\\r`/" # command line under ksh
sed 's/$'"/`echo \\\r`/" # command line under bash
sed "s/$/`echo \\\r`/" # command line under zsh
sed 's/$/\r/' # gsed 3.02.80 or higher
ใช้สำหรับในสถานที่เช่นการแปลงsed -i
sed -i 's/..../' file
\r
:tr "\r" "\n" < infile > outfile
-d
เป็นจุดเด่นบ่อยขึ้นและจะไม่ช่วยใน "เท่านั้น\r
" สถานการณ์
\r
ให้\n
มีผลต่อการเว้นวรรคสองไฟล์; แต่ละบรรทัด CRLF ที่ลงท้ายด้วย DOS จะกลายเป็น\n\n
Unix
การทำสิ่งนี้กับ POSIX นั้นยุ่งยาก:
POSIX Sedไม่สนับสนุนหรือ\r
\15
แม้ว่าจะเป็นเช่นนั้นตัวเลือก in place -i
ไม่ใช่ POSIX
POSIX Awkรองรับ\r
และ\15
อย่างไรก็ตาม-i inplace
ตัวเลือกนี้ไม่ได้เป็น POSIX
d2uและdos2unixไม่ใช่POSIX ยูทิลิตี้แต่อดีตคือ
POSIX อดีตไม่สนับสนุน\r
, \15
, \n
หรือ\12
หากต้องการลบ carriage return ให้ทำดังนี้
ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file
ในการเพิ่มการขึ้นบรรทัดใหม่ให้ทำดังนี้
ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
tr
\r
ดังนั้นคุณสามารถใช้printf '%s\n' '%!tr -d "\r"' x | ex file
(แม้ว่าจะได้รับสิ่งนี้\r
จะถูกลบออกแม้ว่าจะไม่ได้นำหน้าทันที\n
) นอกจากนี้-b
ตัวเลือกที่ex
จะไม่ถูกระบุโดย POSIX
คุณสามารถใช้ vim โดยทางโปรแกรมพร้อมกับอ็อพชัน -c {command}:
Dos เป็น Unix:
vim file.txt -c "set ff=unix" -c ":wq"
Unix to dos:
vim file.txt -c "set ff=dos" -c ":wq"
"set ff = unix / dos" หมายถึงเปลี่ยน fileformat (ff) ของไฟล์เป็น Unix / DOS ในรูปแบบบรรทัด
": wq" หมายถึงเขียนไฟล์ลงดิสก์และออกจากโปรแกรมแก้ไข (อนุญาตให้ใช้คำสั่งในลูป)
vi
จะรู้ว่าสิ่งที่:wq
หมายถึง สำหรับผู้ที่ไม่มี 3 ตัวอักษรหมายถึง 1) พื้นที่คำสั่งเปิด vi, 2) เขียนและ 3) ออกจาก
การใช้ AWK คุณสามารถทำได้:
awk '{ sub("\r$", ""); print }' dos.txt > unix.txt
การใช้ Perl คุณสามารถทำได้:
perl -pe 's/\r$//' < dos.txt > unix.txt
awk
สะดวก
เพื่อแปลงไฟล์ในสถานที่ใช้งาน
dos2unix <filename>
เมื่อต้องการส่งออกข้อความที่แปลงเป็นไฟล์อื่นให้ใช้
dos2unix -n <input-file> <output-file>
คุณสามารถติดตั้งบน Ubuntu หรือ Debian ด้วย
sudo apt install dos2unix
หรือบน macOS โดยใช้homebrew
brew install dos2unix
ปัญหานี้สามารถแก้ไขได้ด้วยเครื่องมือมาตรฐาน แต่มีเพียงพอกับดักมากมายสำหรับเลินเล่อที่ผมขอแนะนำให้คุณติดตั้งflip
คำสั่งที่ถูกเขียนขึ้นในช่วง 20 ปีที่ผ่านมาโดยราหุล Dhesi, zoo
ผู้เขียนของ มันทำงานได้อย่างยอดเยี่ยมในการแปลงรูปแบบไฟล์ในขณะที่หลีกเลี่ยงการทำลายไฟล์ไบนารี่โดยไม่ได้ตั้งใจซึ่งเป็นเรื่องง่ายเกินไปถ้าคุณแค่เปลี่ยนไปเปลี่ยน CRLF ทุกอันที่คุณเห็น ...
การแก้ปัญหาที่โพสต์นั้นจัดการกับปัญหาเพียงบางส่วนโดยแปลง CRLF ของ DOS / Windows ให้เป็น LF ของ Unix ส่วนหนึ่งที่พวกเขากำลังขาดหายไปคือว่าการใช้ CRLF DOS เป็นเส้นคั่นในขณะที่ระบบปฏิบัติการยูนิกซ์ใช้ LF เป็นเส้นTerminator ข้อแตกต่างคือไฟล์ DOS (ปกติ) จะไม่มีอะไรหลังจากบรรทัดสุดท้ายในไฟล์ในขณะที่ Unix จะ ในการแปลงให้ถูกต้องคุณต้องเพิ่ม LF สุดท้ายนั้น (เว้นแต่ไฟล์จะมีความยาวเป็นศูนย์นั่นคือไม่มีบรรทัดเลย) คาถาที่ฉันโปรดปรานสำหรับสิ่งนี้ (ด้วยตรรกะเล็กน้อยที่เพิ่มเข้ามาเพื่อจัดการไฟล์ที่คั่นด้วย CR สไตล์ Mac และไม่ใช่ไฟล์ที่เป็นอันตรายที่อยู่ในรูปแบบ unix อยู่แล้ว) เป็นบิตของ perl:
perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt
โปรดทราบว่าสิ่งนี้จะส่งเวอร์ชัน Unixified ของไฟล์ไปยัง stdout หากคุณต้องการแทนที่ไฟล์ด้วยเวอร์ชัน Unixified ให้เพิ่มการ-i
ตั้งค่าสถานะของ perl
หากคุณไม่มีสิทธิ์เข้าถึงdos2unixแต่สามารถอ่านหน้านี้ได้คุณสามารถคัดลอก / วางdos2unix.py ได้จากที่นี่
#!/usr/bin/env python
"""\
convert dos linefeeds (crlf) to unix (lf)
usage: dos2unix.py <input> <output>
"""
import sys
if len(sys.argv[1:]) != 2:
sys.exit(__doc__)
content = ''
outsize = 0
with open(sys.argv[1], 'rb') as infile:
content = infile.read()
with open(sys.argv[2], 'wb') as output:
for line in content.splitlines():
outsize += len(line) + 1
output.write(line + '\n')
print("Done. Saved %s bytes." % (len(content)-outsize))
dos2unix
แปลงทุกการป้อนข้อมูลไฟล์โดยค่าเริ่มต้น การใช้งานของคุณหมายถึง-n
พารามิเตอร์ และตัวจริงdos2unix
คือตัวกรองที่อ่านจาก stdin เขียนไปยัง stdout หากไม่ได้รับไฟล์
ง่ายสุด ๆ ด้วย PCRE;
เป็นสคริปต์หรือแทนที่$@
ด้วยไฟล์ของคุณ
#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@
สิ่งนี้จะเขียนทับไฟล์ของคุณในสถานที่!
ฉันขอแนะนำให้ทำสิ่งนี้กับการสำรองข้อมูลเท่านั้น (การควบคุมเวอร์ชันหรืออื่น ๆ )
--
งานนี้ถึงแม้ว่าฉันเขียนชื่อไฟล์และไม่มีการ ฉันเลือกโซลูชันนี้เพราะเข้าใจง่ายและปรับให้เข้ากับฉัน FYI, นี่คือสิ่งที่สวิตช์ทำ: -p
สันนิษฐานว่าเป็น "ในขณะที่อินพุต", -i
แก้ไขไฟล์อินพุตในสถานที่, -e
เรียกใช้คำสั่งต่อไปนี้
โซลูชัน awk ที่ง่ายยิ่งขึ้นโดยไม่มีโปรแกรม:
awk -v ORS='\r\n' '1' unix.txt > dos.txt
ในทางเทคนิค '1' เป็นโปรแกรมของคุณ b / c awk ต้องการหนึ่งตัวเลือกเมื่อได้รับ
UPDATE : หลังจากเข้ามาที่หน้านี้เป็นครั้งแรกอีกครั้งในระยะเวลานานฉันรู้ว่ายังไม่มีใครโพสต์โซลูชันภายในดังนั้นนี่คือ:
while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt
awk -v RS='\r\n' '1' dos.txt > unix.txt
awk
หรือเทียบเท่า sed
นอกจากนี้คุณต้องใช้while IFS= read -r line
เพื่อรักษาบรรทัดอินพุตอย่างซื่อสัตย์มิฉะนั้นช่องว่างนำหน้าและต่อท้ายจะถูกตัดแต่ง (หรือไม่ใช้ชื่อตัวแปรในread
คำสั่งและทำงานด้วย$REPLY
)
มีเพียงไตร่ตรองคำถามเดียวกันนั้น (ฝั่ง Windows แต่ใช้ได้กับ linux อย่างเท่าเทียมกัน) ไม่มีใครพูดถึงวิธีอัตโนมัติในการแปลง CRLF <-> LF สำหรับไฟล์ข้อความโดยใช้zip -ll
ตัวเลือกเก่า(Info-ZIP):
zip -ll textfiles-lf.zip files-with-crlf-eol.*
unzip textfiles-lf.zip
หมายเหตุ: สิ่งนี้จะสร้างไฟล์ zip ที่เก็บชื่อไฟล์ดั้งเดิมไว้ แต่จะแปลงไฟล์ลงท้ายด้วย LF จากนั้นunzip
จะแตกไฟล์เป็น zip'ed ซึ่งเป็นชื่อเดิม (แต่ใช้กับ LF-endings) ดังนั้นการแจ้งให้เขียนทับไฟล์ต้นฉบับในเครื่องหากมี
ข้อความที่ตัดตอนมาที่เกี่ยวข้องจากzip --help
:
zip --help
...
-l convert LF to CR LF (-ll CR LF to LF)
น่าสนใจใน git-bash ของฉันบน windows sed ""
ได้ทำการหลอกลวง:
$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text
ฉันเดาว่า sed ไม่สนใจพวกเขาเมื่ออ่านบรรทัดจากอินพุตและมักเขียนจุดสิ้นสุดบรรทัด unix บนเอาต์พุต
สิ่งนี้ใช้ได้สำหรับฉัน
tr "\r" "\n" < sampledata.csv > sampledata2.csv
สำหรับ Mac osx หากคุณติดตั้ง homebrew [ http://brew.sh/ เหมือนพี่น้อง 1]
brew install dos2unix
for csv in *.csv; do dos2unix -c mac ${csv}; done;
ตรวจสอบให้แน่ใจว่าคุณได้ทำสำเนาไฟล์ไว้เนื่องจากคำสั่งนี้จะแก้ไขไฟล์ให้ถูกต้อง ตัวเลือก -c mac ทำให้สวิตช์ทำงานร่วมกับ osx ได้
-c mac
ซึ่งใช้สำหรับการแปลงCR
บรรทัดใหม่pre-OS X เท่านั้น คุณต้องการใช้โหมดนั้นเฉพาะไฟล์ที่ไปและกลับจาก Mac OS 9 หรือก่อนหน้า
TIMTOWTDI!
perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt
ยึดตาม @GordonDavisson
เราต้องคำนึงถึงความเป็นไปได้ของ[noeol]
...
คุณสามารถใช้ awk ตั้งค่าตัวคั่นเรคคอร์ด ( RS
) เป็น regexp ที่ตรงกับอักขระขึ้นบรรทัดใหม่ที่เป็นไปได้ทั้งหมดหรือตัวอักษร และตั้งค่าตัวคั่นเร็กคอร์ดเอาต์พุต ( ORS
) เป็นอักขระบรรทัดใหม่ของยูนิกซ์
awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
git diff
แสดง ^ M, แก้ไขเป็นกลุ่ม)
บน Linux มันง่ายที่จะแปลง ^ M (ctrl-M) เป็น * nix newlines (^ J) ด้วย sed
มันจะเป็นอย่างนี้ใน CLI จริงๆแล้วจะมีการแบ่งบรรทัดในข้อความ อย่างไรก็ตาม, \ ผ่านนั้น ^ J ไปยังใจ:
sed 's/^M/\
/g' < ffmpeg.log > new.log
คุณได้รับสิ่งนี้โดยใช้ ^ V (ctrl-V), ^ M (ctrl-M) และ \ (แบ็กสแลช) ขณะที่คุณพิมพ์:
sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log
sed --expression='s/\r\n/\n/g'
ตั้งแต่คำถามที่กล่าวถึง sed นี่เป็นวิธีที่ตรงไปตรงมาที่สุดในการใช้ sed เพื่อให้บรรลุเป้าหมายนี้ สิ่งที่นิพจน์กล่าวคือแทนที่ carriage-return และ line-feed ด้วยเพียงแค่ line-feed เท่านั้น นั่นคือสิ่งที่คุณต้องการเมื่อคุณเปลี่ยนจาก Windows เป็น Unix ฉันยืนยันว่ามันใช้งานได้
ในฐานะที่เป็นส่วนขยายของโซลูชัน Unix to DOS ของ Jonathan Leffler เพื่อแปลงเป็น DOS ได้อย่างปลอดภัยเมื่อคุณไม่แน่ใจเกี่ยวกับการสิ้นสุดบรรทัดปัจจุบันของไฟล์:
sed '/^M$/! s/$/^M/'
สิ่งนี้ตรวจสอบว่าบรรทัดนั้นยังไม่สิ้นสุดใน CRLF ก่อนที่จะแปลงเป็น CRLF
ฉันสร้างสคริปต์ตามคำตอบที่ยอมรับเพื่อให้คุณสามารถแปลงได้โดยตรงโดยไม่ต้องใช้ไฟล์เพิ่มเติมในตอนท้ายและลบและเปลี่ยนชื่อในภายหลัง
convert-crlf-to-lf() {
file="$1"
tr -d '\015' <"$file" >"$file"2
rm -rf "$file"
mv "$file"2 "$file"
}
ตรวจสอบให้แน่ใจว่าคุณมีไฟล์อย่างเช่น "file1.txt" ที่ "file1.txt2" ไม่มีอยู่แล้วหรือจะถูกเขียนทับฉันจะใช้มันเป็นที่เก็บไฟล์ชั่วคราว
ด้วย bash 4.2 และใหม่กว่าคุณสามารถใช้สิ่งนี้เพื่อตัดส่วนท้ายของ CR ซึ่งใช้ bash ในตัวเท่านั้น:
if [[ "${str: -1}" == $'\r' ]]; then
str="${str:: -1}"
fi
ฉันลอง file.txt ของ sed / s M M // // บน OSX และวิธีอื่น ๆ อีกหลายวิธี ( http://www.thingy-ma-jig.co.uk/blog/25-11-2010/fixing- dos-line-endingsหรือhttp://hintsforums.macworld.com/archive/index.php/t-125.html ) ไม่ทำงานไฟล์ยังคงไม่เปลี่ยนแปลง (จำเป็นต้องใช้ Ctrl-v Enter เพื่อทำซ้ำ ^ M) ในที่สุดฉันใช้ TextWrangler มันไม่ได้เป็นบรรทัดคำสั่งอย่างเคร่งครัด แต่มันใช้งานได้และมันก็ไม่บ่น
dos2unix
โดยใช้ตัวจัดการแพคเกจของคุณจริงๆแล้วมันง่ายกว่ามาก