Gawk: ผ่านอาร์เรย์ไปยังฟังก์ชั่น


9

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

รับรหัส awk นี้เป็นตัวอย่าง ...

function foo(ga) {
  ga[1] = "global result"
}

garray[1] = "global"
foo(garray)

print garray[1]

จะพิมพ์ ...

global result

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

เนื่องจากฉันทำการดีบั๊กและตัว 3.1.6 รู้จักข้อบกพร่องในพื้นที่นี้ฉันกำลังพยายามหาจุดบกพร่องของ awk และจุดเริ่มต้นของฉัน

เพิ่มเติม: เพราะเหตุใด ga [] จึงทำงานภายในฟังก์ชันได้

ก่อนอื่นเลยการส่งอาร์เรย์ไปยังฟังก์ชันด้วยfoo(ga)นั้นไม่จำเป็นจริง ๆ เพียงเข้าใช้งานตามgarray[]ฟังก์ชั่น ไม่มีโทษปรับประสิทธิภาพการทำงานในการทำมันและช่วยในการแก้จุดบกพร่องและการรายงานข้อผิดพลาด

ในการใช้foo(ga), เป็นคำพ้องสำหรับอาร์เรย์ทั่วโลกga[] garray[]แทนที่จะเป็นสำเนาโลคัลgarray[]มันเป็นเพียงตัวชี้ไปgarray[]เช่นลิงก์สัญลักษณ์เป็นตัวชี้ไปยังไฟล์และทำให้สามารถเข้าถึงไฟล์เดียวกัน (หรืออาเรย์) ภายใต้ชื่อมากกว่าหนึ่งชื่อ

เพิ่มเติม: ชี้แจงคำตอบของ Glenn Jackman

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

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: 
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: 

โปรดทราบว่าเราเป็นเพียงการผ่านx[]อาร์เรย์ (ที่จริงเพียงแค่ชี้ไป) bar()เพื่อ y[]อาร์เรย์ไม่ได้อยู่จนกว่าเราจะได้รับภายในฟังก์ชั่น

อย่างไรก็ตามหากเราประกาศy[]โดยรวมไว้ในbar()รายการอาร์กิวเมนต์โดยไม่ต้องกำหนดอะไรนอกฟังก์ชั่นมันจะกลายเป็นมองเห็นได้หลังจากโทรbar(x,y)...

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x,y)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: 
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: hello

ในที่สุดถ้าเราสร้างy[]อาร์เรย์นอกฟังก์ชั่นและส่งผ่านไปด้วยbar(x,y)การsplit()กำหนดภายในฟังก์ชั่นแทนที่องค์ประกอบของอาร์เรย์ที่ ...

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      y[1]="howdy"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x,y)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: howdy
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: hello

คำตอบ:


5

พารามิเตอร์ฟังก์ชั่นท้องถิ่นฟังก์ชั่น

awk '
    function foo(x,y) {y=x*x; print "y in function: "y} 
    BEGIN {foo(2); print "y out of function: " y}
'
y in function: 4
y out of function: 

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

function foo(a, b, c            d, e, f) {...

โดยที่พารามิเตอร์หลัง whitespace เป็นตัวแปรโลคัลและไม่ได้ตั้งใจที่จะรับค่าเมื่อเรียกใช้

ไม่มีเหตุผลว่าทำไมสิ่งนี้ไม่สามารถใช้ได้กับอาร์เรย์ในท้องถิ่น:

awk '
    function bar(x) {
        split("hello world", x)
        print "in: " x[1]
    }
    BEGIN {
        x[1]="world"
        bar()
        print "out: " x[1]}
'
in: hello
out: world

3

เอกสารเพ่งพิศทำให้มันชัดเจนว่าอาร์เรย์จะถูกส่งผ่านโดยการอ้างอิงและไม่มีเอกสารทางรอบที่ พฤติกรรมนี้เหมือนกันกับgawk4.0.1

POSIX ระบุพฤติกรรมนั้นดังนั้นฉันไม่คาดหวังว่าคุณจะพบawkการใช้งานใด ๆที่ทำงานเป็นอย่างอื่น

perlหากคุณต้องการการทำงานที่คุณสามารถใช้ perlมาพร้อมกับเครื่องมือ ( a2p) ในการแปลสคริปต์เพื่อawkperl

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