วิธีใช้ sort บนคำสั่ง awk print?


8

ฉันมีสองคำสั่งในสคริปต์ awk ที่ฉันเขียน:

print "Here are some players and their numbers, sorted by last name"
if(sum[x] > 500) {print x, $2}

ผลลัพธ์ใด:

Here are some players and their numbers, sorted by last name
Lebron James 23
Kevin Durant 35
Kobe Bryant 24
Blake Griffin 32
Dikembe Mutumbo 55

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


3
ให้ความคิดเห็นของคุณในคำตอบดูเหมือนว่าคุณจะสับสนawkและshell script ในคำถามของคุณ ดูเหมือนว่าคุณต้องการทำการเรียงลำดับภายในสคริปต์ awk ของคุณไม่ใช่ในเชลล์สคริปต์ที่เรียกใช้ หากถูกต้องแล้วโปรดแก้ไขคำถามของคุณและแทนที่ทั้งสองเกิดขึ้น 'เปลือก' โดย 'awk' ในหมายเหตุที่แยกต่างหาก: ใช่ awk มีระบบอำนวยความสะดวกในการเรียงลำดับ แต่มีส่วนเกี่ยวข้องค่อนข้างมาก: คุณต้องเก็บทุกบรรทัดในอาเรย์ใส่ไว้ในฟิลด์ที่สองซึ่งคุณต้องแยกออกจากxนั้นตั้งค่าPROCINFO["sorted_in"]เป็นความลับ จากนั้นออกอาร์เรย์ ฉันจะไม่ไปที่นั่น
zwets

1
... | sort -k2,2ฉันหมายความว่าฉันจะไม่ไปที่นั่นได้รับความเรียบง่ายของ
zwets

@zwets ฉันจะใช้งาน...| sort -k2,2อย่างไรหากมีบรรทัดอื่น ๆ ที่จำเป็นต้องพิมพ์ ตรวจสอบคำถามที่ถูกแก้ไข
KM142646

โดยecho-ing บรรทัดส่วนหัวจากเปลือกแล้วเรียกใช้ขั้นawk | sortตอน
zwets

คำตอบ:


12

คุณสามารถเพิ่ม| sort -k2คำสั่งของคุณ สิ่งนี้จะจัดเรียงตามตัวอักษรตามคอลัมน์ที่สอง

ตัวอย่าง:

$ echo "Lebron James 23
Kevin Durant 35
Kobe Bryant 24
Blake Griffin 32
Dikembe Mutumbo 55" | sort -k2

ผลลัพธ์ใน

Kobe Bryant 24
Kevin Durant 35
Blake Griffin 32
Lebron James 23
Dikembe Mutumbo 55

น่าเสียดายที่ฉันกำลังใช้สคริปต์และคำสั่ง sort จะถูกรวมเข้ากับเอาต์พุตอื่น ๆ อีกมากมาย มีวิธีการเรียงลำดับผลลัพธ์{print x, $2}โดยตรงในรหัสสคริปต์หรือไม่ if(sum[x] > 500) {print x, $2} | sort -k2ฉันได้รับข้อผิดพลาดเมื่อท่อ
KM142646

3
@KMoy: if(sum[x] > 500) {print x, $2}เป็นรหัส Awk ในขณะที่| sort -k2เป็นคำสั่งเชลล์ เห็นได้ชัดว่าคุณไม่สามารถผสมสองอย่างนี้เพราะพวกเขาเป็นภาษาที่แตกต่างกัน แต่คุณต้องใช้sortคำสั่งกับเอาต์พุตของตัวแปล Awk ที่รันข้อมูลโค้ด Awk ของคุณ หากคุณไม่ทราบว่าสิ่งที่ฉันหมายถึงโปรดขยายคำถามของคุณเพื่อให้ภาพเต็ม
David Foerster

1
คุณกำลังเขียนเชลล์สคริปต์ใช่ไหม แล้วคุณมีสองตัวเลือกคือ 1. ./my-script.sh | sort -k2วิ่ง 2. เพิ่ม `| เรียงลำดับ -k2` ไปยังบรรทัดของสคริปต์ของคุณที่สร้างผลลัพธ์ที่กำหนดในคำถามของคุณ
Wayne_Yux

@Wayne_Yux โปรดตรวจสอบการแก้ไขกับคำถามเดิม
KM142646

ถ้าอย่างนั้นคุณอาจต้องการคำตอบจาก @steeldriver
Wayne_Yux

9

แม้ว่าฉันจะไม่แนะนำ (เนื่องจากความเรียบง่ายสัมพัทธ์ของการไพพ์ผลลัพธ์ผ่านsortคำสั่งภายนอก) คุณสามารถทำได้อย่างน้อยด้วย GNU awk รุ่นล่าสุด (อย่างน้อย 4.0 IIRC) ตามที่อธิบายไว้ในSorting Array Values ​​and Indices with gawk

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

function mycmp(ia, va, ib, vb, sa, sb) {
  if(split(toupper(ia), sa) && split(toupper(ib), sb)) {
    if(sa[2] < sb[2]) return -1;
    else if (sa[2] > sb[2]) return 1;
    else {
      # compare first names
      if(sa[1] < sb[1]) return -1;
      else if (sa[1] > sb[1]) return 1;
      else return 0;
    }
  }
  else return 0;
}

ตอนนี้คุณสามารถใช้PROCINFO["sorted_in"]วิธีการเรียงลำดับอาร์เรย์ที่กล่าวถึงในความคิดเห็นโดย @zwets

PROCINFO["sorted_in"] = "mycmp";
for(i in a) print i, a[i];

วางไว้ด้วยกัน

#!/usr/bin/gawk -f

function mycmp(ia, va, ib, vb, sa, sb) {
  if(split(toupper(ia), sa) && split(toupper(ib), sb)) {
    if(sa[2] < sb[2]) return -1;
    else if (sa[2] > sb[2]) return 1;
    else {
      # compare first names
      if(sa[1] < sb[1]) return -1;
      else if (sa[1] > sb[1]) return 1;
      else return 0;
    }
  }
  else return 0;
}

{
  a[$1" "$2] = $3;
}

END {
  PROCINFO["sorted_in"] = "mycmp";
  for(i in a) print i, a[i];
}

การทดสอบ:

$ ./namesort.awk yourfile
Kobe Bryant 24
Kevin Durant 35
Blake Griffin 32
Lebron James 23
Dikembe Mutumbo 55

ใน awk รุ่นที่น้อยกว่าหรือเก่าที่สุดทางออกที่ดีที่สุดของคุณอาจจัดเก็บข้อมูลที่ดัชนีโดยLastname Firstnameจัดเรียงตามแบบดั้งเดิมasortiแล้วแยกและสลับเขตข้อมูลของดัชนีในขณะที่คุณสำรวจอาร์เรย์เพื่อพิมพ์:

awk '
  {a[$2" "$1]=$3} 
  END {
    n=asorti(a,b); for (i=1;i<=n;i++) {split(b[i],s); print s[2], s[1], a[b[i]]}
}' yourfile

5

หากต้องการsortเฉพาะช่องที่สองที่คั่นด้วยช่องว่างให้ใช้คีย์-k2,2:

... | sort -k2,2

โดยค่าเริ่มต้นsortการเรียงลำดับพจนานุกรม

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

ตรวจสอบman sortด้วย


โปรดตรวจสอบความคิดเห็นเกี่ยวกับโพสต์ของ Wayne สำหรับสิ่งที่ฉันต้องการ
KM142646

1

ลอง

awk -f myscript.awk | sort -k2

ที่ myscript.awk มีคำสั่ง awk อย่างหมดจด

หากสคริปต์จริงของคุณคือเชลล์สคริปต์คุณมีตัวเลือกมากมายรวมถึง

  • ท่อส่งออกผ่านการจัดเรียง ./myscript.bash | sort -k2
  • เขียนซ้ำรหัสเป็นฟังก์ชันภายในสคริปต์
    แทน

    $ cat t1
    #!/bin/bash
    for i in 2 4 3 1 5;
    do
      echo $i
    done
    
    $ ./t1
    2
    4
    3
    1
    5
    

    ทำ

    $ cat t2
    #!/bin/bash
    function foo {
      for i in 2 4 3 1 5;
      do
        echo $i
      done
    }
    foo | sort
    
    $ ./t2
    1
    2
    3
    4
    5
    

แต่โปรดทราบว่าคุณสามารถใช้การเรียงลำดับกับโครงสร้าง do ... ที่ทำแทนการสร้างฟังก์ชันได้

    do
       echo $i
    done | sort

ทำไมต้องกำหนดฟังก์ชั่น
zwets

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

1

ในการจัดเรียงข้อมูลของคุณเพื่อพิมพ์:

  • สมมติว่าคุณต้องการพิมพ์ฟิลด์ที่ 2 (คั่นด้วยช่องว่าง) ใช้สิ่งนี้:

    awk '{print $2}' data.txt | sort
    

    เช่น:

    $cat>data.txt
    1 Kedar 20
    2 Amit 30
    3 Rahul 21
    ^C
    
    $awk '{print $2}' | sort
    Amit
    Kedar
    Rahul
    
  • หากคุณต้องการพิมพ์ทั้งหมดของคุณdata.txtแต่เรียงลำดับในคอลัมน์ 2 แล้ว:

    $awk '{print}'|sort -k2
    2 Amit 30
    1 Kedar 20
    3 Rahul 21
    

ใช้ตรรกะนี้ในความต้องการของคุณ

คุณอาจจะใช้สำหรับคุณสมบัติที่น่าสนใจมากขึ้นของman sortsort


0

สิ่งที่เกี่ยวกับด้านล่าง:

 awk 'BEGIN{str="1\n2\n3\n4"; system("echo -e \""str"\" | sort -r")}'

มันทำงานได้เมื่อฉันทดสอบ


0
print "Here are some players and their numbers, sorted by last name"
if(sum[x] > 500) {print x, $2 | "sort -k2,2"}

ในการจัดเรียงเอาต์พุตไปยังไฟล์:

print "Here are some players and their numbers, sorted by last name"
if(sum[x] > 500) {print x, $2 | "sort -k2,2 > sortedFile"}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.