Извлечение значения в строке ниже и запись результатов вместе с исходным поисковым термином (linux) - PullRequest
3 голосов
/ 30 апреля 2019

Мне было интересно, может ли кто-нибудь помочь мне с моей проблемой?Я довольно новичок в Linux, и на этом этапе я нахожу руководство пользователя awk непроницаемым.

Скажем, file.txt содержит следующее:

group   position
A       1
A       2
A       5
A       8
B       23
B       556
B       778
C       1

Я хочу найти файл по заданной комбинации столбцов (скажем, группа A, позиция 1), и я хочу вернутьисходная позиция, с позицией на следующей строке в столбце рядом с ней.

Например,

Поиск: A & 1 Возврат: 1 2

Используя grep, я могу вытащитьстрока ниже…

вход:

grep -w -A1 'A.2' file.txt 

Выход:

A       2
A       5

… и если я передам результаты grep в awk, я получу то, что хочу…

input:

awk '{printf "%s%s",$2,(NR%2?FS:RS)}'

Output:

2 5

Пока все хорошо

Все становится сложнее, когда я ищу несколько терминов.

Например, если я искал A.2, A.5 и B.556

Мой требуемый вывод будет:

2   5
5   8
556 778

То, что я получаю:

вход:

grep -w -A1 'A.2\|A.5\|B.556' file.txt  

выход:

A       2
A       5
A       8
--
B       556
B       778

вход:

awk '{printf "%s%s",$2,(NR%2?FS:RS)}'

выход:

2 5
8
556 778

Если я добавлю промежуточную команду, удалив строки, содержащие «-»

awk -F"\t" '$1 != "--"'

, а затем попробую снова запустить команду awk, я получу:

2 5
8 556
778

Может ли кто-нибудь направить меня вправильное направление, чтобы получить результат, который я хотел бы?

Ура!

Ответы [ 3 ]

3 голосов
/ 30 апреля 2019
$ cat tst.awk
BEGIN {
    split(locs,tmp)
    for (i in tmp) {
        tgts[tmp[i]]
    }
}
{ currPos = $2 }
found {
    if (dir != "before") {
        print prevPos, currPos
    }
    found = 0
}
($1"."$2) in tgts {
    if (dir == "before") {
        print prevPos, currPos
    }
    found = 1
}
{ prevPos = currPos }

$ awk -v locs='A.2 A.5 B.556' -f tst.awk file
2 5
5 8
556 778

$ awk -v dir='before' -v locs='A.2 A.5 B.556' -f tst.awk file
1 2
2 5
23 556
2 голосов
/ 30 апреля 2019

Если я правильно понял ваше требование, не могли бы вы попробовать один раз.Я передаю ваши аргументы в awk переменную с именем search, как A 2,B 556 fashion, добавлю больше объяснений через несколько минут.

awk -v search="A 2,B 556" '
flag{
  print array2[2],$2
  flag=""
  val=array2[2]
}
{
  num=split(search,array1,",")
}
{
  for(i=1;i<=num;i++){
     split(array1[i],array2," ")
     if($1==array2[1] && $2==array2[2]){
         flag=1
         next
     }
  }
}
'   Input_file

Вывод будет следующим.

2 5
556 778

Объяснение: Добавление пояснения к вышеуказанному решению.

awk -v search="A 2,B 556" '                  ##Starting awk program here, where mentioning a variable named search which will have your serach values in form of one_value, another_value etc.(as per OP post)
flag{                                        ##Checking condition if variable flag is NOT NULL then do following.
  print array2[2],$2                         ##Printing value of array2 element whose index is 2 and $2 of current line.
  flag=""                                    ##Nullifying variable  flag here.
  val=array2[2]                              ##Creating variable val whose value is array2 value with index 2 here.
}
{
  num=split(search,array1,",")               ##Splitting variable search into array1 whose delimiter is comma.
}
{
  for(i=1;i<=num;i++){                       ##Starting a for loop from i=1 to till value of num(which is length of array1).
     split(array1[i],array2," ")             ##Splitting array1 value of index i with delimiter space into array2.
     if($1==array2[1] && $2==array2[2]){     ##Checking condition if array2 with index 1 value equals to $1 and array2 with index 2 value equals to $2.
         flag=1                              ##Setting variable flag value to 1 here.
         next                                ##Using next keyword of awk to skip all further statements from here.
     }
  }
}
'   Input_file                               ##Mentioning Input_file name here.
1 голос
/ 30 апреля 2019

Чистое решение AWK:

awk 'donext { donext=0; printf("%s%s%s",FS,$2,RS); } /A.2|A.5|B.556/ { donext=1; printf("%s",$2); }'

Тест:

$ awk 'donext { donext=0; printf("%s%s%s",FS,$2,RS); } /A.2|A.5|B.556/ { donext=1; printf("%s",$2); }' file.txt
2 5
5 8
556 778

За комментарий AWK решение для предыдущих записей:

awk '/A.2|A.5|B.556/ { printf("%s%s%s%s",prev,FS,$2,RS); } { prev=$2; }'

Тест:

$ awk '/A.2|A.5|B.556/ { printf("%s%s%s%s",prev,FS,$2,RS); } { prev=$2; }' file.txt
1 2
2 5
23 556
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...