Awk có thể được sử dụng thay thế?


17

Tôi muốn lấy số từ ratingđầu ra từ đây

# nc localhost 9571 
language:
language:en_ZA.UTF-8
language:en_ZW.UTF-8
session-with-name:Ubuntu Classic (No effects):gnome-session --session=2d-gnome
session-with-name:Ubuntu (Safe Mode):gnome-session -f --session=2d-gnome
session-with-name:Ubuntu Classic:gnome-session --session=classic-gnome
xsession:/etc/X11/Xsession
rating:94

Tôi có thể làm như thế này

# nc localhost 9571 | grep rating | cut -d: -f2
94

Nhưng có thể awkđược sử dụng thay thế cho một giải pháp đơn giản hơn?


Câu hỏi này dường như lạc đề vì nó liên quan đến lập trình trong giao diện Awk và có liên quan hơn trên StackOverflow.com
Magellan

Câu trả lời:


32
$ nc localhost 9571 | awk -F: '/rating/ { print $2 }'

7
Có thể đưa ra kết quả sai nếu bất kỳ giá trị hoặc tên trường nào chứa chuỗi "xếp hạng", tức là một trong các tên phiên có từ "xếp hạng" trong đó. Tốt hơn:awk -F: '$1 == "rating" {print $2}'
Ingmar Hupp

3
Hoặc có thể awk -F: '/^rating:/ { print $2 }'?
một CVn

Tôi biết điều đó, nhưng tôi chuyển đổi dựa trên lệnh của OP.
lượng tử

@IngmarHupp Tôi nghĩ chính xác điều tương tự. Trên thực tế, rất phù hợp với hồ sơ chính xác trong câu hỏi mà tôi đã chỉnh sửa câu trả lời với thay đổi này. Điều này hy vọng sẽ giúp mọi người học cách sử dụng awk hiệu quả hơn.
Dan Mould

14

Quanta đánh bại tôi, nhưng tôi sẽ bao gồm một sedbiến thể nếu bạn theo hướng đó:

nc localhost 9571 | sed -ne 's/^rating://p'

Ditto những gì MadHatter nói, mặc dù. Giải pháp hiện tại của bạn là hoàn hảo. (Mặc dù tôi muốn grep "^rating:"thay vì chỉ từ để đảm bảo bạn chỉ nhận được dòng bạn muốn.)


Tôi tình yêu sed! Nó không được sử dụng đúng mức và bị đánh giá thấp ...
Mei

9

Bạn cũng có thể chỉ cần sử dụng shell:

nc localhost 9571 | 
while IFS=: read key val; do [[ $key = "rating" ]] && echo "$val"; done

Đây là cách nhanh nhất - và ngăn chặn sinh sản bất kỳ quá trình nào nc. Đẹp!
Mei

7

có, bạn có thể (và nên) sử dụng (một) awk thay vì (hai) grep và cắt:

$ nc localhost 9571 | awk -F: '/^rating:/ { print $2 }'

Hãy chắc chắn để phù hợp với bạn dòng tốt nhất có thể để tránh các lỗi xấu xí.

  • /rating/ làm,
  • /^rating/ tốt hơn (an toàn hơn),
  • /^rating:/ là tốt nhất (trong trường hợp này).

4

Nó có thể:

nc localhost 9571  | awk -F: '{ if ($1 == "rating") print $2 }' 

(Tôi không biết bạn đang làm gì với localhost ở trên, vì vậy đã sử dụng đầu ra của bạn làm đầu vào cho lệnh awk của tôi, sau đó thay thế "cat" bằng "nc ..." - nhưng nó sẽ ổn thôi.)

Nhưng tại sao bạn lại làm điều này? Cách thức UNIX là có rất nhiều công cụ nhỏ, mỗi công cụ làm tốt một việc, kết hợp với nhau thông qua các đường ống, thay vì sử dụng các công cụ đa chức năng lớn hơn. Bạn cần chọn một dòng khớp duy nhất, chọn một trường từ đó: grepchọn các dòng có khớp và cutchọn các trường từ các dòng đầu vào; chúng hoàn hảo cho nhiệm vụ Nhưng nếu bạn thực sự muốn làm tất cả trong một với awk, tốt, bạn sẽ đi.


Một lý do là việc sử dụng grepcutyêu cầu sinh ra hai quá trình và sử dụng awk(hoặc sed) chỉ cần một. Sinh ra một quá trình là tính toán tốn kém. Ngoài ra, không giống như sử dụng perlhoặc ruby(et al), sedawknhẹ hơn nhiều về phía trước.
Mei

2
Đủ công bằng, mặc dù tôi lưu ý rằng kích thước của nhị phân awk trên hệ thống (F15) của tôi là 360948 byte, trong khi grep và các nhị phân cắt cùng nhau là 170824. Vì vậy, ít chu kỳ hơn chỉ với một fork + exec, nhưng nhiều bộ nhớ hơn và nhiều IO hơn để lấy đĩa nhị phân ra. Thành thật mà nói, tôi nghi ngờ rằng bất kỳ cân nhắc nào trong số những điều này đều quan trọng trên các hệ thống hiện đại, nhưng nếu bạn có ý định giảm thiểu, bạn sẽ đi!
MadHatter hỗ trợ Monica

Foo Bah: cảm ơn về đề xuất chỉnh sửa của bạn, nhưng quanta đã tạo một bài đăng muộn hơn của tôi, thậm chí còn hợp lý hơn đề xuất của bạn. Tôi thích phần mềm của tôi hơn vì người dùng awk cấp nhập cảnh dễ dàng hơn để xem cách thức hoạt động của nó và do đó đã từ chối chỉnh sửa của bạn. Cảm ơn bạn đã suy nghĩ, mặc dù!
MadHatter hỗ trợ Monica

3

Mặc dù câu trả lời của quanta là dễ nhất và tôi cũng sẽ viết, tôi cá là bạn không biết GNU awk (gawk) cũng có thể kết nối mạng ? Bạn có thể viết toàn bộ bằng awk nếu bạn thực sự muốn:

BEGIN {
    FS = ":"
    f = "/inet/tcp/0/127.0.0.1/9571"
    while ((f |& getline) > 0)
        if ($1 ~ /^rating$/) {print $2}
}

Điều này có thể hữu ích nếu máy chủ không cài đặt nc, nc bị hạn chế perm hoặc nếu bạn thực sự thích awk.


Ôi. Đẹp. Mạng một ví dụ đồng xử lý.
Bác sĩ Edward Morbius

0

Bạn cũng có thể sử dụng sed,

nc localhost 9571 | sed -n "s/^rating:\([\d]*\)/\1/p"

Điều này sẽ đảm bảo rằng "xếp hạng" bắt đầu dòng và các chữ số tuân theo rating:


0

Nếu Perl là một tùy chọn:

nc localhost 9571 | perl -F: -lane 'print $F[1] if /rating/'

-aautosplits mỗi dòng vào @Fmảng
-F:sử dụng :làm dấu tách trường, thay vì mặc định khoảng trắng
/rating/trả về true nếu regex được tìm thấy
$F[1]là phần tử thứ 2 của @Fmảng.
Mảng Perl bắt đầu bằng phần tử 0, trong khi awk bắt đầu bằng $ 1

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.