Gawk: Truyền mảng cho các hàm


9

Bị mắc kẹt với GNU awk 3.1.6 và nghĩ rằng tôi đã khắc phục các lỗi mảng của nó nhưng vẫn có vấn đề giống như phạm vi trong chương trình awk 600 dòng. Cần xác minh sự hiểu biết về phạm vi mảng trong awk để tìm lỗi của tôi.

Cho mã awk minh họa này ...

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

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

print garray[1]

sẽ in ...

global result

Vì các mảng luôn được truyền cho các hàm bằng tham chiếu, nên tất cả các mảng luôn là toàn cục. Không có cách nào để tạo một mảng cục bộ. Điều này có đúng không? Đã không thể tìm thấy các tài liệu nói rõ ràng rằng.

Vì tôi đang gỡ lỗi và bản thân 3.1.6 đã biết các lỗi trong khu vực này, nên tôi đang cố gắng xác định nơi các lỗi của awk rời đi và tôi bắt đầu.

Bổ sung: Tại sao ga [] hoạt động bên trong hàm?

Trước hết, việc truyền mảng cho hàm foo(ga)thực sự không cần thiết. Chỉ cần truy cập nó như garray[]bên trong chức năng. Tuy nhiên, không có hình phạt hiệu suất có thể đo lường được khi thực hiện nó và nó giúp gỡ lỗi và báo cáo lỗi.

Trong việc sử dụng foo(ga), ga[]là một từ đồng nghĩa cho mảng toàn cầu garray[]. Thay vì là một bản sao cục bộ garray[], nó chỉ đơn giản là một con trỏ tới garray[], giống như một liên kết tượng trưng là một con trỏ tới một tệp và do đó cùng một tệp (hoặc mảng) có thể được truy cập dưới nhiều tên.

Bổ sung: Làm rõ câu trả lời của Glenn Jackman

Trong khi các mảng được tạo bên ngoài một hàm là toàn cục cho hàm và có thể được truyền cho nó hoặc chỉ được tham chiếu bên trong nó, các mảng được tạo bên trong một hàm thực sự vẫn là cục bộ của hàm và không hiển thị bên ngoài hàm. Sửa đổi ví dụ của ông Jackman minh họa điều nà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)
      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: 

Lưu ý rằng chúng ta chỉ truyền x[]mảng (thực ra, chỉ là một con trỏ tới nó) bar(). Các y[]mảng thậm chí không tồn tại cho đến khi chúng tôi có được bên trong hàm.

Tuy nhiên, nếu chúng ta khai báo y[]bằng cách đưa nó vào bar()danh sách đối số mà không gán bất cứ thứ gì cho nó bên ngoài hàm, nó sẽ hiển thị sau khi gọi 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

Cuối cùng, nếu chúng ta tạo y[]mảng bên ngoài hàm và chuyển nó đi bar(x,y), thì split()phép gán bên trong hàm sẽ thay thế các phần tử của mảng đó ...

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

Câu trả lời:


5

Các tham số chức năng là cục bộ của chức năng.

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: 

Nếu bạn truyền ít giá trị hơn cho một hàm so với các tham số, thì các tham số phụ sẽ trống. Đôi khi bạn có thể thấy các hàm được định nghĩa như

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

trong đó các tham số sau khoảng trắng là các biến cục bộ và không có ý định lấy giá trị khi gọi.

Không có lý do tại sao điều này không thể làm việc cho các mảng cục bộ:

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

Các tài liệu gawk làm cho nó rõ ràng rằng mảng được truyền bằng tham chiếu, và không có ghi nhận con đường xung quanh đó. Hành vi tương tự với gawk4.0.1.

POSIX chỉ định hành vi đó , vì vậy tôi không mong đợi bạn sẽ tìm thấy bất kỳ awktriển khai nào có hành vi khác.

Nếu bạn cần chức năng đó, bạn có thể sử dụng perl. perlđi kèm với một công cụ ( a2p) để dịch awkcác tập lệnh sang perl.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.