การเรียงลำดับที่ไม่ซ้ำกัน: เปลี่ยนเส้นทางเอาต์พุตไปยังไฟล์เดียวกัน


14

มีวิธีสั้น ๆ ในการบันทึกเอาต์พุตไปป์เป็นไฟล์เดียวกับที่ประมวลผลหรือไม่ ตัวอย่างเช่นนี่คือสิ่งที่ฉันกำลังทำอยู่

$ cat filename | sort | uniq > result
$ rm -f filename
$ mv result filename

ฉันสงสัยว่ามีวิธีที่จะทำได้ในหนึ่งบรรทัด (ไม่ต่อท้ายคำสั่งเหล่านั้นโดยใช้ &&)

นี่ไม่ใช่วิธี แต่จะได้รับความคิด

$ cat filename | sort | uniq > filename

2
echo $(cat filename | sort | uniq > result) > filenameหรือบางสิ่งบางอย่าง ? เพียงผ่านฉันไม่มีเวลาลอง
MrVaykadji

คำตอบ:


18

คุณสามารถใช้spongeจากแพ็คเกจmoreutils :

LC_ALL=C sort -u filename | sponge filename

นอกจากนี้คุณยังไม่จำเป็นต้องใช้ไพพ์uniqเนื่องจากเมื่อsortมี-uตัวเลือกสำหรับบรรทัดที่ไม่ซ้ำกันเมื่อเรียงลำดับ

โปรดทราบว่าในระบบ GNU ที่มีโลแคล UTF-8 sort -uหรือsort | uniqไม่ได้ให้บรรทัดที่ไม่ซ้ำกัน แต่เป็นลำดับแรกจากลำดับของบรรทัดที่เรียงลำดับเดียวกันในโลแคลปัจจุบัน

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=en_US.utf8 sort | LC_ALL=en_US.utf8 uniq

ให้คุณ การเปลี่ยนโลแคลเป็น C บังคับให้ลำดับการเรียงตามค่าไบต์:

$ export LC_ALL=C
$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C sort | LC_ALL=C uniq


12

คุณไม่ต้องการคำสั่งพิเศษใด ๆ เช่นcatและuniqโดยไม่ต้องใช้rmคำสั่งและmvคำสั่งเพื่อลบและเปลี่ยนชื่อไฟล์ เพียงใช้คำสั่งง่ายๆ

sort -u filename -o filename


 -u, --unique
        with -c, check for strict ordering; without -c, output only  the
        first of an equal run

 -o, --output=FILE
        write result to FILE instead of standard output

มันทำงานยังไง?

sortคำสั่งเรียงชื่อไฟล์ของคุณและมี-uตัวเลือกลบบรรทัดที่ซ้ำกันออกจากมัน จากนั้นด้วย-oตัวเลือกที่เขียนออกไปยังไฟล์เดียวกันกับวิธีการในสถานที่


3
หากระบบขัดข้องเมื่อsortทำงานคุณจะหลวมไฟล์ต้นฉบับของคุณ
cuonglm

@Gnouc ดังนั้นนี่คือจุดจบของโชคร้าย !! : '(
αғsнιη

1
ขอบคุณ! ในตัวอย่างนี้ด้วย´sort´ โดยเฉพาะฉันควรทำอย่างนั้น อย่างไรก็ตามฉันกำลังคิดเกี่ยวกับกรณีทั่วไป @Gnouc ฮ่าฮ่าไม่มีทางที่จะคิดว่าถ้ามันไม่เกิดขึ้นกับคุณใช่มั้ย?
whitenoisedb

3

ตัวอย่างที่แนะนำของคุณ (ด้านล่าง) ไม่ทำงานเนื่องจากคุณจะต้องอ่านและเขียนไฟล์เดียวกันพร้อมกัน

$ cat filename | sort | uniq > filename

แนวคิดที่มีไพพ์หรือการเปลี่ยนทิศทางคือคำสั่งทางด้านซ้ายและขวาของแต่ละไพพ์หรือการรีไดเร็กต์พร้อมกัน คำสั่งทางด้านขวาประมวลผลข้อมูลตามที่ได้รับจากคำสั่งทางด้านซ้ายในขณะที่คำสั่งทางด้านซ้ายยังคงทำงานอยู่

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

วิธีที่ดีกว่าในการทำเช่นนี้โดยทั่วไปคือในตัวอย่างก่อนหน้าของคุณที่คุณเปลี่ยนเส้นทางไปยังไฟล์ชั่วคราวจากนั้นเปลี่ยนชื่อไฟล์นั้นกลับไปเป็นต้นฉบับ (ยกเว้นว่าคุณไม่จำเป็นต้องลบไฟล์ก่อนเนื่องจากการลบเป้าหมายที่มีอยู่แล้ว) .

$ cat filename | sort | uniq > result
$ mv -f result filename

คุณสามารถบันทึกลงในตัวแปรสตริงได้ยกเว้นว่าจะใช้งานได้เมื่อข้อมูลมีขนาดเล็กพอที่จะใส่ลงในหน่วยความจำพร้อมกันทั้งหมด


เมื่อมีคนนำเสนอในการแก้ไขที่แนะนำคุณสามารถเปลี่ยนcat filename | sortเป็นเพียงsort filename- catไม่จำเป็นที่นี่
thomasrutter

ตัวอย่างด้านล่างไม่ใช่วิธีที่จะทำ ขอบคุณสำหรับการชี้แจง catอาจไม่จำเป็นในกรณีนี้ แต่ฉันมุ่งเน้นไปที่ส่วนการเปลี่ยนเส้นทาง
whitenoisedb

1
ฉันอธิบายว่าทำไมตัวอย่างด้านล่างของคุณไม่ทำงาน ฉันรู้ว่าคุณรู้ว่ามันใช้งานไม่ได้
thomasrutter

ขอบคุณสำหรับการชี้แจง! อันที่จริงฉันไม่รู้ว่าเกิดอะไรขึ้นจริง ๆ
whitenoisedb

2

คุณสามารถใช้teeคำสั่ง:

sort -u filename | tee filename > /dev/null

teeคำสั่งอ่านจากอินพุตมาตรฐานและเขียนออกมาตรฐานและไฟล์


2
สิ่งนี้ไม่ได้ผลสำหรับฉัน
pjvandehaar

3
มันใช้งานไม่ได้กับaskubuntu.com/a/752451
Steven Penny

มันใช้งานได้สำหรับฉัน เช่นเพื่อย้ายบรรทัดไปที่ด้านล่างของไฟล์: ใช้(cat ~/file | grep -v 3662 ; printentry 3662) | tee ~/file > /dev/nullงานได้ ชอบโพสต์ต้นฉบับนี้ไม่ทำงานถ้าคุณเพียงแค่ได้โดยไม่ต้อง> ~/file teeTee ดูคล้ายกับที่นี่sort -o fileซึ่งเขียนไปยังไฟล์ที่มีชื่อ
Joshua Goldberg

เดี๋ยวก่อนขอโทษ! ฉันเคยเห็นสังเกตุว่าจะสูญเสียข้อมูลที่ไม่คาดคิดตามที่อธิบายในลิงก์จาก @Steven ทำไฟล์ด้วยหมายเลข 1..9 บน 9 บรรทัด ต่อไปนี้จะใช้งานได้หลายครั้งและบางครั้งก็ลบข้อมูลทั้งหมดออกจากไฟล์: (cat x | grep -v 7 ; echo 7) | tee x > /dev/null; cat x ฉันขอแนะนำไฟล์ชั่วคราวและmvหรืออาจเป็นทางออกจากลิงก์ของ @ Steven
Joshua Goldberg

@JoshuaGoldberg คุณเห็นคำตอบของฉันในหน้านี้หรือไม่
Steven Penny

0

คุณสามารถใช้ Vim ในโหมด Ex:

ex -sc 'sort u|x' filename
  1. sort u จัดเรียงที่ไม่ซ้ำกัน

  2. x เขียนถ้ามีการเปลี่ยนแปลง (พวกเขามี) และออกจาก

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