มีทางเลือกอื่นสำหรับ sed ที่รองรับ Unicode หรือไม่


33

ตัวอย่างเช่น:

sed 's/\u0091//g' file1

ตอนนี้ฉันต้องทำhexdumpเพื่อให้ได้เลขฐานสิบหกและใส่ลงsedไปดังนี้:

$ echo -ne '\u9991' | hexdump -C
00000000  e9 a6 91                                          |...|
00000003

แล้ว:

$ sed 's/\xe9\xa6\x91//g' file1

คำตอบ:


28

เพียงใช้ไวยากรณ์นั้น:

sed 's/馑//g' file1

หรือในรูปแบบที่หลบหนี:

sed "s/$(echo -ne '\u9991')//g" file1

(โปรดทราบว่า Bash เวอร์ชันเก่าและบางเชลล์ไม่เข้าใจecho -e '\u9991'ดังนั้นให้ตรวจสอบก่อน)


1
sed นับว่า馑เป็นตัวละครเดียวหรือ 3 ตัวหรือไม่? นั่นคือecho 馑 | sed s/...//พิมพ์อะไรหรือไม่
253751

@immibis เนื่องจากsedมีตัวดัดแปลง g มันจะแทนที่การเกิดขึ้นทั้งหมดเช่นกันเมื่อพวกเขาติดตามกัน นอกจากนี้ยัง sed ควรนับว่าเป็นตัวละครตัวหนึ่งดู: ให้echo -ne "馑" | wc -m 1ถ้าคุณนับไบต์ ( wc -c) 3มันก็จะกลับมา ฉันเข้าใจคำถามของคุณถูกต้องหรือไม่?
ความโกลาหล

ฉันหมายถึง: ไม่.หมายถึง "หนึ่งตัวละคร" หรือ "หนึ่งไบต์"?
253751

@immibis ฉันตรงกับตัวละครตัวหนึ่งด้วยเหตุนี้echo 馑 | sed s/...//ทำให้ผม(ไม่มีอะไรจะถูกแทนที่)
ความวุ่นวาย

4
@chaos: ใช้งานได้en_US.UTF-8แต่ไม่Cทำงาน
choroba

15

Perl สามารถทำได้:

echo 汉典“馑”字的基本解释 | perl -CS -pe 's/\N{U+9991}/Jin/g'

-CS เปิด UTF-8 สำหรับอินพุตเอาต์พุตและข้อผิดพลาดมาตรฐาน


7
Perl สามารถทำอะไรก็ได้เกือบทุกอย่าง .....
wobbily_col

6

รองรับหลายรุ่นsedUnicode :

  • มรดกตกทอด sedซึ่งขึ้นอยู่กับ "วัสดุ Unix ดั้งเดิม"
  • GNU sedซึ่งเป็น codebase ของตัวเอง
  • Plan 9 sedซึ่งได้รับการแจ้งความกับระบบปฏิบัติการ Unix

ฉันไม่สามารถหาข้อมูลเกี่ยวกับ BSD sed ได้ซึ่งฉันคิดว่าแปลก แต่ฉันคิดว่าอัตราต่อรองนั้นดีว่ามันรองรับ Unicode ด้วย น่าเสียดายที่ไม่มีวิธีมาตรฐานที่จะบอกได้sedว่าการเข้ารหัสแบบใดที่จะใช้ดังนั้นแต่ละคนจึงทำสิ่งนี้ในรูปแบบของตัวเอง


พวกเขาสนับสนุน UTF-16 ที่มีและไม่มี BOM หรือไม่
Bon Ami

10
UTF-16 นั้นใช้งานไม่ได้ในระบบปฏิบัติการ Unix นอกจากนี้ยังเป็นสิ่งที่น่ารังเกียจที่ไม่เคยเห็นแสงแห่งวัน
ไบรอัน Bi

พวกเขาสนับสนุน UTF-16 หรือไม่นั้นขึ้นอยู่กับการนำไปใช้และฉันเกรงว่าฉันไม่มีข้อมูลนั้น ฉันสงสัยว่า Plan 9 sed ทำ (ระบบปฏิบัติการดั้งเดิมคือ UTF-8 ทุกที่) แต่ฉันไม่สามารถมั่นใจได้และแม้ว่ามันจะไม่เป็นเช่นนั้น
The Spooniest

2

สิ่งนี้ใช้ได้กับฉัน:

$ vim -nEs +'%s/\%u9991//g' +wq file1

มันลดลงมากขึ้นกว่าที่ฉันต้องการ; นี่คือคำอธิบายแบบเต็ม:

  • -n ปิดใช้งานไฟล์สลับเป็นกลุ่ม
  • -E Ex ปรับปรุงโหมด
  • -s โหมดเงียบ
  • +'%s/\%u9991//g' รันคำสั่งการทดแทน
  • +wq บันทึกและออก

ฉันคิดว่าสิ่งนี้แก้ไขfile1 ในสถานที่ที่ถูกต้อง?
gerrit

@gerrit ถูกต้องและขอบคุณที่ชี้ให้เห็น
Aryeh Leib Taurog

1

ด้วย BASH เวอร์ชันล่าสุดเพียงละเว้นเครื่องหมายอัญประกาศล้อมรอบนิพจน์ sed และคุณสามารถใช้สตริง escape ของ BASH ช่องว่างภายในนิพจน์ sed หรือบางส่วนของนิพจน์ sed ที่อาจตีความโดย BASH เนื่องจากสามารถใช้อักขระตัวแทนได้

$ echo "饥馑荐臻" | sed s/$'\u9991'//g
饥荐臻

นี่ควรเป็นคำตอบใหม่ที่ได้รับการยอมรับง่ายและสะอาด!
Allen Wang

0

ทำงานได้สำหรับฉันด้วย GNU sed (รุ่น 4.2.1):

$ echo -ne $'\u9991' | sed 's/\xe9\xa6\x91//g' | hexdump -C
$ echo -ne $'\u9991' | hexdump -C
00000000  e9 a6 91

(เป็นการทดแทนอื่นที่sedคุณสามารถใช้ GNU ได้awkแต่ดูเหมือนว่ามันไม่จำเป็น)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.