Как распечатать только конкретный товар? - PullRequest
0 голосов
/ 27 июня 2019

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

RPT_LINKS=1,T1999
RPT_NUMALINKS=1
RPT_ALINKS=1,1999TK,2135,2009,31462,29467,2560
RPT_TXKEYED=1
RPT_ETXKEYED=0

Я использовал grep, чтобы изолировать интересующую меня строку с RPT_ALINKS.В этой строке я хочу знать, как использовать AWK для печати только ссылки, заканчивающейся TK.

Я действительно близок к запуску этого:

grep -w 'RPT_ALINKS' stats2.log | awk -F 'TK' '{print  FS }'

Но я уверен, что те, ктоумнее меня, я уже знаю, что я получаю только ТЗ назад, как мне получить все поле, чтобы я получил возврат 1999TK?

Ответы [ 6 ]

3 голосов
/ 27 июня 2019

Если в этой строке только один RT и RT всегда в конце:

awk '/RPT_ALINKS/{match($0,/[^=,]*TK/); print substr($0,RSTART,RLENGTH)}'

Вы также можете использовать двойную grep

grep -w 'RPT_ALINKS' stats2.log | grep -wo '[^=,]*TK'

Следующее решение sed также хорошо работает:

sed '/RPT_ALINKS/s/\(^.*[,=]\)\([^=,]*TK\)\(,.*\)\?/\2/'
2 голосов
/ 27 июня 2019

Вот простое решение

awk -F ',|=' '/^RPT_ALINKS/ { for (i=1; i<=NF; i++) if ($i ~ /TK$/) print $i }' stats2.log

Это выглядит только на записи, которая начинается с RPT_ALINKS.И там это проверяет каждое поле.Если поле заканчивается TK, оно печатается.

2 голосов
/ 27 июня 2019

Более элегантно не получается

awk -F '=' '$1=="RPT_ALINKS" {n=split($2,array,",")
            for(i=1; i<=n; i++)
              if (array[i] ~ /TK$/)
                {print array[i]}}
           ' stats2.log

n=split($2,array,","): разделить 1,1999TK,2135,2009,31462,29467,2560 с , на массив array.n содержит количество элементов массива, здесь 7.

1 голос
/ 27 июня 2019

С помощью sed, который имеет -E для ERE, например, GNU или OSX / BSD sed:

$ sed -En 's/^RPT_ALINKS=(.*,)?([^,]*TK)(,.*|$)/\2/p' file
1999TK

С GNU awk для соответствия 3-го аргумента ():

$ awk 'match($0",",/^RPT_ALINKS=(.*,)?([^,]*TK),.*/,a){print a[2]}' file
1999TK
1 голос
/ 27 июня 2019

Черт, я как раз собирался опубликовать альтернативу двойного grep, но получил информацию. И все хорошие решения awk также приняты.

Вздох. Итак, мы идем в Баш, ради интереса.

$ mapfile a < stats2.log
$ for i in "${a[@]}"; do [[ $i =~ ^RPT_ALINKS=(.+,)*([^,]+TK) ]] && echo "${BASH_REMATCH[2]}"; done
1999TK

Недостатком является то, что он работает медленнее, чем awk, и не использует поля. О, и он не будет обрабатывать несколько *TK элементов в одной строке. И, как и sed, это строки обработки в виде шаблонов , а не полей , что лишает элегантности. И используя mapfile, мы ограничиваем размер ввода, который вы можете обрабатывать, потому что весь ваш журнал загружен в память. Конечно, вам не нужно этого делать, но если вы собираетесь использовать трубу, вы все равно будете использовать другой инструмент. : -)

Счастливого четверга.

0 голосов
/ 27 июня 2019

Вместо того, чтобы проходить через него, вы можете использовать другую альтернативу.
Это будет быстро, цикл занимает время.

awk -F"TK" '/RPT_ALINKS/ {b=split($1,a,",");print a[b]FS}' stats2.log
1999TK

Здесь вы разделяете строку, устанавливая разделитель полей на TK и ищите строку, содержащую RPT_ALINKS
Это дает $1=RPT_ALINKS=1,1999 и $2=,2135,2009,31462,29467,2560
$1 всегда будет иметь значение после последней запятой.
Так что разделите это, используя функцию разделения через запятую. b будет содержать количество полей.
Так как мы знаем, что число будет в последнем разделе, мы используем a[b] и добавляем FS, который содержит TK

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...