Как связать операторы awk print?

844
tjt263

Хорошо, вот быстрый пример; изолировать IPV4 хоста в три этапа:

ip -br a lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 DOWN wlan0 UP 192.168.0.101/24 fe80::9fcd:45fb:1e0f:a1cc/64 
ip -br a | awk '/wlan0/ ' 192.168.0.101/24 
ip -br a | awk '/wlan0/ ' | awk -F '/' '' 192.168.0.101 

Вместо вызова второго экземпляра awk(передача вывода одного в следующий); как это можно сделать за один раз?


Просто хотел сказать: вопрос не в разборе вывода ip . Мне просто нужен был быстрый пример, чтобы проиллюстрировать вопрос; это было первое, что я придумал. Настоящий вопрос обобщен в заголовке.

Во всяком случае, для чего это стоит (я должен буду проверить это, но я почти уверен); это то, что я сделал в (недавнем) прошлом:

ip -br a s dev wlan0 | awk -F '[ /]*' '' 192.168.0.101 
5

5 ответов на вопрос

2
Stephen Rauch

Вы можете использовать gsub для этого как:

ip -br a | awk '/wlan0/ ' 
2
John1024

Просто измените определение разделителя полей, чтобы включить оба пробела и /:

$ ip -br a | awk -F'[[:blank:]/]+' '/wlan0/' 192.168.0.101 

Опция -F'[[:blank:]/]+'говорит awk использовать любую комбинацию пробелов, табуляций или косых черт в качестве разделителя полей при вводе.

Это дает правильный результат для примера `ip`. Но ОП говорит, что `ip` является * просто * иллюстративным примером; реальный вопрос: как вы делаете `awk '' | awk -F '/' '' `в одной команде` awk`, и этот ответ не выполняется, если первое или второе (разделенное пробелами) слово во входной строке содержит `/`. В частности, он выведет третье подполе первого слова или первое или второе подполе второго слова, в этом случае. G-Man 6 лет назад 0
2
Chris

Для этого экземпляра самый простой способ сделать это, вероятно, установить несколько разделителей с помощью регулярного выражения:

ip -br a | awk -F '[\t /]*' '/wlan0/ ' 

Это делает разделитель полей любой строкой /, пробелами или табуляцией, а затем печатает третье поле.

Чтобы выполнить любые две произвольные команды, вам нужно выучить полный язык программирования awk. Я бы рекомендовал против этого - я уверен, что у вас есть дела поважнее.

Это дает правильный результат для примера `ip`. Но ОП говорит, что `ip` является * просто * иллюстративным примером; реальный вопрос: как вы делаете `awk '' | awk -F '/' '' `в одной команде` awk`, и этот ответ не выполняется, если первое или второе (разделенное пробелами) слово во входной строке содержит `/`. В частности, он выведет третье подполе первого слова или первое или второе подполе второго слова, в этом случае. G-Man 6 лет назад 0
@ G-Man Я полностью согласен, что мой иллюстративный пример - это не полное решение, а всего лишь уловка, которая работает в этом случае. Но в этом моя суть - нет * общего * метода для объединения операторов awk: вам нужен отдельный «трюк» для каждого. Таким образом, «для выполнения любых * произвольных * двух команд вам в значительной степени необходимо выучить полный язык программирования awk». Chris 6 лет назад 0
2
Joe

Хотя другие ответы решают основную проблему, на самом деле они не отвечают на вопрос: «Как мне связать операторы awk print?»

Для такого рода проблем ответ таков: «Вы этого не делаете». Вы используете оставшуюся часть языка для манипулирования источником, пока не получите желаемый результат - то, что делают два других ответа. Вы используете только printдля вывода окончательного результата.

После того как вы указали начальный шаблон диапазона, например /wlan0/(или /^wl/в моем случае, потому что у моего WiFi другое имя), ваше действие, код внутри {}, будет работать только на входных строках, которые содержат эту строку.

Если у вас есть это, вы можете делать все, что вам нужно, с этой строкой ввода.

ip -br a | \ awk ' /^wl/ { ip1 = $3 gsub(/\/.*/, "", ip1) print ip1 } ' 

Этот код занимает требуемое поле, помещает его в переменную, редактирует содержимое этой переменной и затем печатает его.

Другой ответ делает то же самое более эффективно, но это иллюстрирует более общий случай, когда могут быть добавлены другие шаги. Вы даже можете сохранить результат для последующего использования с чем-то, найденным в другой строке ввода и т. Д.

Для чего-то, что на самом деле может больше походить на «цепочку печати», в awk есть sprintf()функция, которая может сделать отформатированный вывод своего ввода в переменную для дальнейшей обработки.

Или, если вы печатаете более чем одну вещь в строке, ваш код может использовать несколько printf()операторов без перевода строки до последней строки для построения выходной строки по частям.

Это лучший ответ на этот вопрос: как вы делаете `awk '' | awk -F '/' '' `в одной команде` awk`? Но как бы вы обобщили это как `awk '' | awk -F '/' '' `? Например, чтобы напечатать `fox` с учетом ввода` wlan0 foo / bar / quick / brown / fox / jumps / over / the lazy / dog`? G-Man 6 лет назад 0
0
G-Man

Это несколько в духе ответа Стивена Рауха и ответа Джо, но лучше:

awk '/wlan0/ ' 

Это берет третье поле ( $3) и splits его, используя /в качестве разделителя. Компоненты идут в массив a, и возвращается число подполей. (В этом фрагменте я игнорирую возвращаемое значение.) Так же  a[1]как и первое /подпредельное поле третьего поля.

Это легче обобщить, чем другие ответы. Например, если ваш ввод

Однажды в полночь тоскливо, пока я размышлял, слабый и усталый, За многими странными и любопытными томами забытых знаний… wlan0 foo / bar / быстрый / коричневый / лиса / прыжки / лени / собака Пока я кивнул, чуть не вздремнув, внезапно раздался стук, Как будто кто-то мягко постучал - постучал в дверь моей комнаты.

тогда команда

awk '/wlan0/ ' 

напечатает четвертое подполе третьего поля третьей строки ( fox), после проверки возвращаемого значения из, split чтобы убедиться, что есть (как минимум) четыре подполя. То есть это как

awk '/wlan0/ ' | awk -F '/' '' 

в одной awkкоманде, с проверкой ошибок.