awk với câu lệnh if


8

Tôi đang cố gắng in từ một tệp bằng awk, nhưng đầu ra của tôi trống. Đây là mã của tôi cho đến nay

accountNum=$1
while read -r LINE || [[ -n $LINE ]] ; do
            awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts
done < Accounts

Tôi cũng đã thử điều này:

accountNum=$1
while read -r LINE || [[ -n $LINE ]] ; do
            echo $LINE  | awk -F',' '{ if($1==accountNum) { print $3.$2 } }' 
done < Accounts

Tệp đầu vào là:

1,Doe,John
2,Rooney,Wayne
3,Smith,Will
4,Crow,Russel
5,Cruise,Tom

Đầu ra dự kiến ​​khi tôi chạy tệp là

$./file.sh 3
Will Smith

Nhưng tôi nhận được như sau

$./file.sh 3
$

Đó là không có gì đang được in ra. Tôi biết giải pháp với cắt, nhưng tôi muốn sử dụng awk.

Câu trả lời:


8

Bạn nên sử dụng -vtùy chọn awk:

awk -F',' -v accNum="$1" '$1 == accNum {print $3,$2}'

Với $1trích dẫn kép, shell sẽ xử lý tất cả các ký tự đặc biệt (nếu có) cho bạn.


3

Bạn có:

accountNum=$1
awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts

Làm thế nào để biến vỏ accountNumđược vào awk? Nó không: bạn cần cung cấp giá trị của nó awkmột cách rõ ràng. Bạn có thể dùng:

awk -F',' '{ if($1=='"$accountNum"') { print $3.$2 } }' Accounts

để lại dấu ngoặc đơn và có vỏ thay thế giá trị của biến vào awklệnh, sau đó nhập lại dấu ngoặc đơn cho phần còn lại của chuỗi lệnh.

Một kịch bản tốt hơn hoặc ít nhất là thành ngữ sẽ là:

#!/bin/sh
accountNum=$1
awk -F, '$1 == "'"$accountNum"'" { print $3,$2 }' Accounts

liên quan đến số tài khoản không phải là số (trích dẫn biến được thay thế), sử dụng khối mẫu thay vì rõ ràng if( {}khối sẽ chạy nếu kiểm tra trước khi đúng) và in khoảng trắng giữa các tên bạn muốn (vì ,). Nếu bạn muốn sử dụng ifrõ ràng, hãy di chuyển bài kiểm tra bên trong ifcâu lệnh hiện tại của bạn .

Tùy thuộc vào mục tiêu thực sự của bạn awkcó thể không phù hợp nhất với những gì bạn đang làm. Ở trên vẫn không thành công nếu tập lệnh $1có dấu ngoặc kép trong đó. Vòng lặp shell bạn đã không làm bất cứ điều gì hữu ích, mặc dù nó sẽ lặp lại đầu ra nhiều lần.


bạn đang nói tôi nên loại bỏ whilevòng lặp? :)
gkmohit

Ít nhất là đối với các ví dụ, nó không làm gì để giúp bạn.
Michael Homer

3

Kịch bản của bạn thực tế đã thực hiện công việc mà không có chút nào awk:

while IFS=, read -r num last first
    do  [ $((num==accountNum)) -eq 1 ] && 
        printf '%s.%s\n' "$first" "$last"
done < Accounts

Tôi không gợi ý rằng đây là một giải pháp tốt hơn hoặc hiệu quả hơn so với sử dụng awkmột mình, nhưng nếu bạn muốn while...readvòng lặp, điều này chắc chắn sẽ đánh bại các awkquy trình riêng biệt trên mỗi dòng. Chỉ là một FYI, tôi đoán.


Không chỉ một awk cho mỗi dòng, mà awk đó đọc lại toàn bộ tệp cho mỗi dòng mà chính shell đó đọc. Cách để có được thuật toán O (n ^ 2).
Paul_Pedant

1
#!/bin/bash

awk -v a="$1" -F ',' '$1 == a { print $3, $2 }' Accounts

Với việc -v a="$1"chúng ta đặt awkbiến athành giá trị của đối số dòng lệnh đầu tiên của tập lệnh, sau đó chúng tôi xác định rằng đầu vào được phân tách bằng dấu phẩy -F ','. Nếu cột đầu tiên bằng giá trị của a, hãy in hai cột khác theo thứ tự ngược lại.

Bạn không nhận được gì trong đầu ra của mình khi bạn đang so sánh cột đầu tiên với awkbiến accountNum, không được đặt.

Nếu có một mục có cột đầu tiên có 0 (không) trong đó, mục đó sẽ được in. Điều này là do giá trị của các biến unset trong awkước tính bằng không.

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.