Можно ли вместо этого использовать awk?

17

Я хотел бы получить номер в ratingкачестве вывода из этого

# 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

Я могу сделать это так

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

но можно было awkбы использовать вместо этого для более простого решения?

Sandra
источник
Этот вопрос, кажется, не по теме, потому что он касается программирования в интерфейсе Awk и более актуален на StackOverflow.com
Magellan

Ответы:

32
$ nc localhost 9571 | awk -F: '/rating/ { print $2 }'
кванты
источник
7
Может давать неверные результаты, если какое-либо из значений или имен поля содержит строку «rating», т.е. в одном из имен сеанса есть слово «rating». Лучше:awk -F: '$1 == "rating" {print $2}'
Ингмар Хапп
3
Или может быть awk -F: '/^rating:/ { print $2 }'?
CVn
Я знаю это, но я конвертирую на основе команды ОП.
кванты
@IngmarHupp Я думал точно так же. На самом деле, гораздо точнее сопоставить с конкретной записью, что я отредактировал ответ с этим изменением. Надеемся, что это поможет людям научиться использовать awk более эффективно.
Дэн Молдинг
14

Кванта опередил меня, но я включу sedвариант, если вы склонны так:

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

То же самое сказал и MadHatter. Ваше текущее решение отлично звучит. (Хотя я предпочел бы "^rating:"не просто слово, чтобы убедиться, что вы получите только ту строку, которую хотите.)

SmallClanger
источник
Я люблю sed! Он так недооценен и недооценен ...
Мэй,
9

Вы также можете просто использовать оболочку:

nc localhost 9571 | 
while IFS=: read key val; do [[ $key = "rating" ]] && echo "$val"; done
Гленн Джекман
источник
Это самый быстрый способ - и предотвращает порождение любых процессов за его пределами nc. Ницца!
Мэй
7

да, вы можете (и должны) использовать (один) awk вместо (двух) grep и cut:

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

Будьте уверены, чтобы соответствовать вашей линии как можно лучше, чтобы избежать уродливых ошибок.

  • /rating/ работает,
  • /^rating/ лучше (безопаснее),
  • /^rating:/ лучше всего (в этом случае).
Михал Шрайер
источник
4

Он может:

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

(Я не знаю, что вы делаете с localhost выше, поэтому использовал ваш вывод в качестве входных данных для моей команды awk, а затем заменил «cat» на «nc ...» - но это должно быть хорошо.)

Но зачем ты это делаешь? Способ UNIX состоит в том, чтобы иметь множество небольших инструментов, каждый из которых хорошо выполняет свою задачу, соединенных вместе с помощью конвейеров, а не с помощью более крупных многофункциональных инструментов. Вам нужно выбрать одну совпадающую строку, выбрать из нее одно поле: grepвыбрать строки с совпадениями и cutвыбрать поля из входных строк; они идеально подходят для этой задачи. Но если вы действительно хотите сделать это все в одном с помощью awk, ну, вот и все.

Безумный Шляпник
источник
Одна из причин заключается в том, что для использования grepи cutтребуется порождение двух процессов, а для использования awk(или sed) требуется только один. Создание процесса является вычислительно дорогим. Кроме того, в отличие от использования perlили ruby(и др.), sedИ awkгораздо более легкий фронт.
Мэй
2
Вполне справедливо, хотя я отмечаю, что размер двоичного файла awk в моей системе (F15) составляет 360948 байт, в то время как двоичные файлы grep и cut вместе составляют 170824. Таким образом, меньше циклов только с одним fork + exec, но больше памяти и больше IO чтобы получить двоичный файл с диска. Честно говоря, я сомневаюсь, что любое из этих соображений имеет значение для современных систем, но если вы склонны к минимизации, то вы идете!
MadHatter
Фу Бах: спасибо за ваше предложение по редактированию, но Quanta сделал пост позже, чем мой, что еще более упорядочено, чем ваше предложение. Я предпочел мой, потому что пользователю awk начального уровня легче увидеть, как он работает, и поэтому отклонил ваше редактирование. Спасибо за мысль, хотя!
MadHatter,
3

Хотя ответ Кванты самый простой и тот, который я бы написал тоже, держу пари, вы не знали, что GNU awk (gawk) тоже может работать в сети ? Вы можете написать все это с помощью awk, если вы действительно хотите:

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

Это может быть полезно, если на сервере не установлен nc, nc имеет ограниченные привилегии или если вам действительно нравится awk.

Марк Маккинстри
источник
Оооо. Ницца. Сеть и пример сопроцессинга.
Доктор Эдвард Морбиус
0

Вы также можете использовать Sed,

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

Это будет гарантировать, что «рейтинг» начинает строку, и что цифры следуют за rating:

Sirch
источник
0

Если Perl вариант:

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

-aавтоматическое разбиение каждой строки в @Fмассиве
-F:используется :в качестве разделителя полей, вместо значения по умолчанию пробела
/rating/возвращает значение true, если найдено регулярное выражение,
$F[1]являющееся вторым элементом @Fмассива.
Массивы Perl начинаются с элемента 0, тогда как awk начинается с $ 1

Крис Кокнат
источник