แถวที่ปรับได้จากคอลัมน์เดี่ยวถึงหลายคอลัมน์และ Cols AWK

ฉันมีข้อมูลอินพุตที่มีลักษณะเช่นนี้ในรูปแบบ "ดด/ปปปป ข้อมูล":

Location 1
08/2012, 44.1
09/2012, 34.2
10/2012, 24.3
11/2012, 14.4
12/2012, 04.5
01/2013, 14.6
02/2013, 24.7
Location 2
08/2012, 33.1
09/2012, 44.2
10/2012, 55.3
11/2012, 66.4
12/2012, 77.5
01/2013, 88.6
02/2013, 11.7
Location 3
08/2012, 35.1
09/2012, 45.2
10/2012, 55.3
11/2012, 66.4
12/2012, 77.5
01/2013, 71.6 
02/2013, 19.7
Location 4
etc
etc

และฉันใช้สคริปต์ awk นั่นคือสิ่งนี้ -

awk '}printf (NR %276 == 0 )? $0"\n" : $0"\t" }' inputfile (ฉันใช้ NR%276 เพราะนั่นคือความยาวของคอลัมน์สำหรับแต่ละคอลัมน์ที่ทำซ้ำใหม่หรือ "ตำแหน่ง" ในข้อมูลต้นฉบับที่แสดงในส่วนด้านบน) Awk สามารถแบ่งส่วนข้อมูล col เดี่ยวจาก "Location X" เป็น "Location Y" ใน n cols ของเอาต์พุตได้หรือไม่

ฉันได้รับเอาต์พุต แต่มันไม่ถูกต้องในการรันเอาต์พุตจากไฟล์อินพุต col เดี่ยวในแนวนอนในรูปแบบการตัดข้อความหรือ "งู" เช่นนี้ - ตำแหน่ง 1 มม./ปปปป, data1 data2 ฯลฯ ตำแหน่ง 2 มม./ปปปป, data1 data2 ฯลฯ ตำแหน่ง 3 มม./ปปปป, data1 data2 ฯลฯ

แต่ฉันต้องการให้ข้อมูลเอาต์พุตของฉันมีลักษณะเช่นนี้ แต่สำหรับ 276 แถวและประมาณ 150 คอลัมน์/ตำแหน่ง หรือไปยังส่วนคอลัมน์เดียวสุดท้ายของข้อมูล "ตำแหน่ง" จำนวน 276 แถวในไฟล์อินพุต (ตัวอย่างแบบย่อที่แสดงด้านบน) จะเป็นประโยชน์หากเพิ่มจำนวนแถวเป็น 277 แถว เช่น สำหรับ 03/2013 หรือเป็น >150 ตำแหน่ง

Location 1        Location 2        Location 3
08/2012, 44.1     08/2012, 33.1     08/2012, 35.1
09/2012, 34.2     09/2012, 44.2     09/2012, 45.2
10/2012, 24.3     10/2012, 55.3     10/2012, 55.3
11/2012, 14.4     11/2012, 66.4     11/2012, 66.4
12/2012, 04.5     12/2012, 77.5     12/2012, 77.5
01/2013, 14.6     01/2013, 88.6     01/2013, 71.6
02/2013, 24.7     02/2013, 11.7     02/2013, 19.7

ขอบคุณ!!


awk
person user2100039    schedule 18.03.2013    source แหล่งที่มา


คำตอบ (3)


awk อื่นที่คุณสามารถลองได้:

awk '!/^[0-9]/{n=0} {n++; A[n]=A[n] (A[n]?OFS:x) $0} END{for(i=1; i<=n; i++) print A[i]}' OFS='\t' file

หากต้องการพิมพ์เฉพาะคอลัมน์ที่สองในแต่ละสถานที่:

awk '!/^[0-9]/{n=0} {n++; A[n]=A[n] (A[n]?OFS:x) $2} END{for(i=1; i<=n; i++) print A[i]}' OFS='\t' file
person Scrutinizer    schedule 18.03.2013
comment
โอเค มันได้ผล ฉันต้องหาวิธีพิมพ์เพียง $2 หรือคอลัมน์ที่สองสำหรับแต่ละสถานที่หรือส่วนหัวของคอลัมน์ มีความคิดอะไรบ้าง? ขณะนี้กำลังพิมพ์ทั้ง $1 และ $2 ขอบคุณ, - person user2100039; 19.03.2013
comment
@ user2100039: เพิ่มการแก้ไขด่วน - person Scrutinizer; 19.03.2013

ลองใช้ซับเดียวนี้:

 awk '/^Location/{j=0;++i}{l[i,++j]=$0}END{for(m=1;m<=j;m++){for(n=1;n<=i;n++)printf l[n,m] (n==i?"":"\t");print ""}}' file

หมายเหตุ

  • บรรทัดด้านบนแปลงอินพุตหนึ่งคอลัมน์ของคุณเป็นเอาต์พุต 3 คอลัมน์ ไม่สามารถจัดการ 276 rows เนื้อหาของคุณได้ (ฉันไม่คิดว่าเราจำเป็นต้องคำนวณแบบนั้น)
  • ในเอาต์พุต คอลัมน์จะถูกแยกออกจากกัน tab
  • แถวและคอลัมน์ไม่ได้ฮาร์ดโค้ด คุณสามารถทดสอบกับข้อมูลจริงของคุณได้

ทดสอบกับข้อมูลของคุณ:

kent$  awk '/^Location/{j=0;++i}{l[i,++j]=$0}END{for(m=1;m<=j;m++){for(n=1;n<=i;n++)printf l[n,m] (n==i?"":"\t");print ""}}' file      
Location 1      Location 2      Location 3
08/2012, 44.1   08/2012, 33.1   08/2012, 35.1
09/2012, 34.2   09/2012, 44.2   09/2012, 45.2
10/2012, 24.3   10/2012, 55.3   10/2012, 55.3
11/2012, 14.4   11/2012, 66.4   11/2012, 66.4
12/2012, 04.5   12/2012, 77.5   12/2012, 77.5
01/2013, 14.6   01/2013, 88.6   01/2013, 71.6 
02/2013, 24.7   02/2013, 11.7   02/2013, 19.7

แก้ไข สำหรับความคิดเห็น

 awk '!/^[0-9]/{j=0;++i}{l[i,++j]=$0}END{for(m=1;m<=277&&m<=j;m++){for(n=1;n<=i;n++)printf l[n,m] (n==i?"":"\t");print ""}}' file 
  • บรรทัดด้านบนจะไม่ตรงกับ 'ตำแหน่ง' แบบฮาร์ดโค้ด แต่สำหรับชื่อที่ไม่ใช่ตัวเลข (ใช้ได้กับ "สถานที่" เช่นกัน)
  • 276, 277 ฉันไม่รู้ว่ามันหมายถึงอะไร แต่หนึ่งซับด้านบนจะใช้สำหรับแต่ละบล็อก (ตำแหน่งในตัวอย่างของคุณ) พิมพ์สูงสุด 276 แถว ถ้าจำนวนแถวน้อยกว่า 276 ให้พิมพ์จำนวนแถวตามจริง

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

ขอให้โชคดี.

person Kent    schedule 18.03.2013
comment
ขออภัย ส่วนหัว Col Location 1 ฯลฯ ใช้สำหรับตัวอย่างนี้ แต่ในความเป็นจริงแล้ว ชื่อเหล่านั้นมีการเปลี่ยนแปลง ดังนั้น Location จะไม่ปรากฏในไฟล์อินพุต มันสามารถค้นหาความยาวของสตริงแทนได้หรือไม่? - person user2100039; 18.03.2013
comment
ในไฟล์อินพุตแถวของข้อมูล = 276 และรวมส่วนหัวของแถว = 277 ขอบคุณอีกครั้ง - - person user2100039; 18.03.2013
comment
@ user2100039 แล้วอะไรคือตำแหน่งในข้อมูลจริงของคุณ? ทำตามรูปแบบบางอย่างใช่ไหม? อย่างไรก็ตาม ฉันคิดว่าสายการบินเดียวของฉันช่วยให้คุณเริ่มต้นได้ - person Kent; 18.03.2013
comment
ชื่อเช่น Eagle, Westridge, MesaTop ฯลฯ ที่ไม่ซ้ำกันสำหรับส่วนหัวแต่ละอัน + ข้อมูล 276 แถว ขอบคุณ, - person user2100039; 18.03.2013
comment
มีปัญหาหลังจาก [0-9]/{j=0; - regexp ที่ไม่ถูกยุติบน { ก่อน j ไอเดีย? - person user2100039; 18.03.2013

สมมติว่าแต่ละสถานที่มีจำนวนแถวข้อมูลเท่ากัน:

numcols=$(tac input_file | awk '$1 == "Location" {print $2; exit}')
pr -t -s --columns=$numcols input_file

เนื่องจากคุณทราบจำนวนแถวในแต่ละสถานที่ ให้คำนวณจำนวนสถานที่ด้วย:

numcols=$(( $(wc -l < input_file) / 277 ))
person glenn jackman    schedule 18.03.2013
comment
ขอบคุณ - ส่วนหัว Location ในไฟล์จริงไม่ได้ใช้คำว่า Location แต่เป็นตำแหน่งที่ไม่ซ้ำกัน เช่น Flatiron, Wolfbog, Mesavista เป็นต้น แถวข้อมูลคือ = 276 + ส่วนหัวสำหรับแต่ละส่วนของข้อมูลที่ต้องพิมพ์เป็น คอลัมน์ใหม่ ขอบคุณ! - person user2100039; 18.03.2013
comment
Glenn- ฉันได้รับข้อผิดพลาดชื่อตัวแปรที่ไม่ถูกต้องเมื่อฉันเรียกใช้โค้ดนี้ และข้อความแสดงข้อผิดพลาดเดียวกันเมื่อเรียกใช้โค้ด numcols แยกกันเพื่อค้นหาจำนวนตำแหน่ง ไอเดีย? - person user2100039; 19.03.2013
comment
จริงหรือ คุณใช้เชลล์อะไร (bash/csh/...) แสดงรหัสที่คุณใช้งานจริงให้เราดู โปรดสังเกตวงเล็บด้านนอกเป็นสองเท่าและวงเล็บด้านในเป็นแบบเดี่ยว - person glenn jackman; 19.03.2013