Cách lập trình phát hiện hương vị awk (ví dụ gawk vs nawk)


8

Tôi đang sử dụng một ứng dụng dòng lệnh về cơ bản là một tập hợp các tập lệnh bash shell. Ứng dụng này được viết để chạy trên BSD / OSX và cả trên Linux. Một trong những kịch bản dựa trên awk. Nó chứa hai lệnh awk: một lệnh được viết cho nawk (triển khai awk BSD tiêu chuẩn) và một lệnh được viết cho gawk (triển khai GNU awk).

Hai lệnh awk trong câu hỏi không tương thích chéo với các môi trường khác nhau; đặc biệt là lệnh nawk thất bại khi chạy với gawk. Kịch bản kiểm tra tên kernel (tức là uname -s) để xác định môi trường máy chủ, và sau đó chạy lệnh awk thích hợp. Tuy nhiên, tôi thích làm việc trên Mac OS X với các tiện ích lõi GNU được cài đặt, do đó tập lệnh không chạy đúng.

Trong quá trình suy nghĩ về cách tốt nhất để khắc phục lỗi này, tôi nhận ra rằng thật tuyệt khi biết cách phân biệt lập trình giữa các hương vị khác nhau của các tiện ích dòng lệnh thông thường, tốt nhất là theo cách tương đối mạnh mẽ và di động.

Tôi nhận thấy rằng nawk không chấp nhận cờ '-V' để in thông tin phiên bản, vì vậy tôi đoán rằng một cái gì đó như sau sẽ hoạt động:

awk -V &>/dev/null && echo gawk || echo nawk

Một biến thể khác có thể là:

awk -Wversion &>/dev/null && echo gawk || echo nawk

Điều này dường như hoạt động trên hai môi trường thử nghiệm của tôi (OS X và CentOS). Đây là câu hỏi của tôi:

  • Đây có phải là cách tốt nhất để đi?
  • Có cách nào để mở rộng điều này để xử lý các biến thể khác của awk (ví dụ: mawk, jawk, v.v.) không?
  • Nó có đáng để lo lắng về các phiên bản khác của awk không?

Tôi cũng nên đề cập rằng tôi biết rất ít về awk.


Nếu lệnh awk không quá phức tạp hoặc thậm chí nếu có, bạn có thể xem xét chuyển nó sang perl hoặc một cái gì đó khác là thống nhất.
tự đại diện

Hãy xem phiên bản awk awk -Wvthay vì môi trường máy chủ
Costas

1
Awk của tôi rất yếu nhưng tôi tin rằng nó khá đơn giản. Tôi thực sự đã viết lại nó trong bash tinh khiết. Nhưng đây là một trong những tình huống mà tôi quan tâm đến việc thỏa mãn sự tò mò của mình hơn là thực sự giải quyết vấn đề ban đầu.
igal

@Costas Một cái gì đó như thế thực sự đã xảy ra với tôi, nhưng tôi không chắc nó có thể dễ vỡ đến mức nào; Tôi biết rất ít về awk. Tôi đã thêm giải pháp hiện tại vào bài viết của mình.
igal

1
Một cách khác là bỏ qua phiên bản nào awkđang được sử dụng và mã cho đặc tả POSIX thay thế.
chepner

Câu trả lời:


7
if awk --version 2>&1 | grep -q "GNU Awk"
then
    awk 'BEGIN {print "I am GNU Awk"}'

elif awk -Wv 2>&1 | grep -q "mawk"
then
    awk 'BEGIN {print "I am mawk"}'

else
    awk 'BEGIN {print "I might be nawk, might not be"}'
fi

Ngoài ra, kiểm tra là awk là một liên kết tượng trưng:

awk=$( command -v awk )
[[ -L $awk ]] && readlink $awk # make some decision about the result of that

Cái này thì không sao ... nhưng có một vài biến thể (khó phân biệt) cho các phiên bản cũ-awk, nawk và các phiên bản BWK mới hơn. Đối với những người, một kịch bản mẫu có thể được tùy chỉnh.
Thomas Dickey

3

Hãy thử sử dụng whichlệnh và sử dụng mã thoát của nó.

which nawk
if [[ $? == 0 ]]; then
    command="nawk"
else
    command="gawk"
fi

sau đó định dạng tập lệnh của bạn để sử dụng biến làm lệnh

$command '{print $1}` 

sẽ được đọc là

nawk '{print $1}`

nếu whichtìm thấy nawk. Nếu không nó sẽ sử dụnggawk


1
commandlà một bash dựng sẵn, bạn có thể muốn sử dụng một tên khác cho biến của mình và bạn cũng có thể muốn xem câu trả lời cực kỳ chi tiết về lý do tại sao đối với nhiều shell, có những lựa chọn thay thế tốt hơn whichtại unix.stackexchange.com/a/85250/109842
Eric Renouf

1

GNU Awk thường được cài đặt dưới dạng gawk, với awktư cách là một liên kết tượng trưng cho nó trên các hệ thống mà GNU là mặc định. Tôi đoán đây là trường hợp trên các hệ thống BSD và OS X, vì chúng đã có sẵn awk.

if gawk '{ exit; }' < /dev/null 2> /dev/null
then
    echo "gawk available"
else
    echo "gawk not available"
fi

Cảm ơn về thông tin bạn vừa nhập. Đây là một ý tưởng tốt và bạn chính xác rằng đây là trường hợp của tôi trên OS X. Nhưng tôi đã hy vọng về một giải pháp nội tại, có thể nói như vậy.
igal

0

Một hack bẩn

if nawk 'BEGIN { nawk-only-function() ;}' 
then 
   nawk -f nfile.awk ...
else 
   gawk -f gfile.awk ...
fi
  • nơi nawk-only-function() chỉ tồn tại trênnawk

-2

Có lẽ tôi sẽ thử lạm dụng macro AC_PROG_AWK m4 trong autoconf để chọn một thứ tự, sắp xếp chúng một cách thích hợp. Có lẽ nó quá mức cần thiết


Bạn có thể chỉnh sửa để cung cấp thêm một chút chi tiết về cách bạn sử dụng macro đó cho kịch bản này không?
Michael Homer

Nó không thực sự cho biết cái nào nó tìm thấy, mà chỉ đơn giản là tìm kiếm các triển khai awk và chọn một cái dựa trên tên của nó.
Thomas Dickey
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.