Sử dụng biến shell trong awk


8

Đây là tập lệnh của tôi (để tìm các tệp có chứa một mẫu đã chỉ định):

find . -type f \
    -exec awk -v vawk="$1" '/'"$vawk"'/ {c++} c>0 { print ARGV[1]; exit 0 } END { if (! c) {exit 1}}' \{\} \;

Tôi muốn sử dụng tập lệnh của mình với một đối số §:

MyScript.sh pattern

Vấn đề của tôi là tôi không quản lý để đưa $1biến vào awk.

Khi tôi cố gắng gỡ lỗi kịch bản của mình

bash -x MyScript.sh pattern

Đây là đầu ra:

+ find . -type f -exec awk -v vawk=pattern '// {c++} c>0 {print ARGV[1] ; exit 0 } END { if (! c) {exit 1}}' '{}' ';'

Các $vawkbiến dường như là trống rỗng.

Bất kỳ ý tưởng?

Câu trả lời:


7

Bạn dường như đang nhầm lẫn các biến awk và biến shell. awk -v vawk="$1"tạo một biến awk được gọi vawk, nhưng bạn đang cố gắng sử dụng cú pháp shell ( $vawk). Điều này không hoạt động vì shell không có một biến được gọi vawk. Tôi nghĩ những gì bạn muốn là

awk -v vawk="$1" '$0 ~ vawk { c++ } # ...'
#                      ^ awk variable syntax

1
Lưu ý rằng awkmở rộng các chuỗi thoát giống như C $1, để cách tiếp cận không hoạt động nếu $1có thể chứa các ký tự dấu gạch chéo ngược (phổ biến cho biểu thức chính quy). Bạn có thể sử dụng ENVIRONmảng đặc biệt awk thay thế.
Stéphane Chazelas

6

Đã sao chép từ câu hỏi này bây giờ đóng lại dưới dạng câu hỏi trùng lặp vì nó bao gồm các cảnh báo về những hạn chế của biến awk mà người ta có thể thấy hữu ích.

Một biến shell chỉ là: một biến shell . Nếu bạn muốn biến nó thành một biến awk , bạn cần một cú pháp như:

awk -v x="$x" '$2 == x {print $1}' infile

hoặc là

awk '$2 == x {print $1}' x="$x" infile

Tuy nhiên, những vấn đề này gặp phải một vấn đề: các chuỗi thoát được mở rộng trong chúng (và với GNU awk4.2 trở lên, nếu $xbắt đầu bằng @/và kết thúc /, nó được coi là một loại biến regrec ).

Vì vậy, ví dụ, nếu biến shell chứa hai ký tự dấu gạch chéo ngượcn , biến awk sẽ kết thúc chứa tự dòng mới (và với gawk 4.2+, nếu nó chứa @/foo/, biến awk sẽ chứa foovà có kiểu regexp).

Một cách tiếp cận khác (nhưng giống như -vyêu cầu một POSIX awk hoặc nawk (trái ngược với awk của 1970 vẫn được tìm thấy như /bin/awktrong Solaris)) là sử dụng các biến môi trường:

x="$x" awk '$2 == ENVIRON["x"] {print $1}' infile

Một cách tiếp cận khác (vẫn với awks mới hơn) là sử dụng mảng ARGV trong awk:

awk 'BEGIN {x = ARGV[1]; delete ARGV[1]}
  $2 == x {print $1}' "$x" infile
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.