Как выбрать содержимое в другом столбце в файле с оболочкой linux? - PullRequest
2 голосов
/ 09 мая 2019

У меня есть файл. Этот файл имеет около 3000 строк

Я выбрал четыре строки. Содержание как:

user=bio-wangxf group=bio-jinwf etime=1556506215 start=1556506216 unique_node_count=1 end=1556524815 Exit_status=0
user=bio-wangxf group=bio-jinwf jobname=cellranger start=1556506216 end=1556555583 Exit_status=0 resources_used.cput=338425
user=maad-inspur01 group=maad-huangsd jobname=2d-1d9-4.3-1152-RK2 queue=cal-l start=1554626044 exec_host=cu017/0-23 end=1554626044
user=maad-inspur01 group=maad-huangsd jobname=testmatlab queue=cal-l ctime=1554632326 qtime=1554632326 etime=1554632326 start=1554632328 owner=maad-inspur01@ln01 exec_host=cu191/0-11 Resource_List.nodect=1 Resource_List.nodes=1:ppn=12 session=15549 unique_node_count=1 end=1554643410 Exit_status=0 resources_used.cput=7102 resources_used.mem=31315760kb resources_used.vmem=96803568kb resources_used.walltime=03:04:42
user=iese-liul group=iese-zhengchm jobname=ssh queue=fat ctime=1555483302 qtime=1555483302 etime=1555483302 start=1555489505 owner=iese-liul@ln04 exec_host=fat02/0-17,126-142 Resource_List.neednodes=1:ppn=35 Resource_List.nodect=1 Resource_List.nodes=1:ppn=35 Resource_List.walltime=72:00:00 session=31961 total_execution_slots=35 unique_node_count=1 end=1555498389 Exit_status=0 resources_used.cput=38523 

Теперь я хочу выбрать пользователя, группу, начало, конец.

Правильный результат должен быть таким:

user=bio-wangxf group=bio-jinwf start=1556506216 end=1556524815
user=bio-wangxf group=bio-jinwf start=1556506216 end=1556555583
user=maad-inspur01 group=maad-huangsd start=1554626044 end=1554626044
user=maad-inspur01 group=maad-huangsd start=1554632328 end=1554643410
user=iese-liul group=iese-zhengchm start=1555489505 end=1555498389

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

Я пытался:

awk '{if($15~/end/) print $1" "$2" "$4" "$15; else if($18~/end/) print $1" "$2" "$8" "$18}' filename

Не могу получить правильный результат. некоторые строки пропущены, потому что начало и конец не в фиксированном столбце.

Кто может мне помочь?

Ответы [ 4 ]

4 голосов
/ 09 мая 2019

Вы все еще можете использовать awk:

$ awk '{
    for(i=1;i<=NF;i++)                       # loop fields
        if($i~/^(user|group|start|end)=/)    # look for keyword
            b=b (b==""?"":OFS) $i            # buffer matching field
    print b                                  # print buffer
    b=""                                     # reset and repeat
}' file

Вывод:

user=bio-wangxf group=bio-jinwf start=1556506216 end=1556524815
user=bio-wangxf group=bio-jinwf start=1556506216 end=1556555583
user=maad-inspur01 group=maad-huangsd start=1554626044 end=1554626044
user=maad-inspur01 group=maad-huangsd start=1554632328 end=1554643410
user=iese-liul group=iese-zhengchm start=1555489505 end=1555498389

Поля будут выводиться в исходном порядке.

1 голос
/ 09 мая 2019

Когда у вас есть файл с записями / строками, которые состоят из пар ключ-значение в виде key1=value1_FS_key2=value2_FS_key3=value3 ..., где _FS_ - разделитель полей (разделитель), я обычно храню все пары ключ-значение в массиве.где вы можете использовать ключ для поиска значения или объекта интереса.В данном случае это полная комбинация ключ-значение.

В awk это читается как:

awk '{for(i=1;i<=NF;++i) if(match($i,"=")) a[substr($i,1,RSTART-1)]=$i}
     { print a["user"],a["group"],a["start"],a["end"] }
     { delete a }' file

Этот метод чрезвычайно гибкий и совместим с POSIX.Следующие модификации легко сделать:

  • Изменить разделитель полей: awk 'BEGIN{FS=OFS=";"}{...}'
  • Изменить поля, которые вы хотите вывести: просто обновите оператор печати

Конечно, проблема может возникнуть, если вы хотите напечатать ключ, которого нет в строке.Предположим, что «группа» не доступна в строке, в настоящее время она напечатает что-то вроде:

user=bio-wangxf  start=1556506216 end=1556555583

Это может быть не то, что вы хотите, и, возможно, вы хотели бы иметь что-то вроде

user=bio-wangxf group=NA start=1556506216 end=1556555583

Это можно сделать с помощью простой функции

awk 'function lookup(key) { return (key in a ? a[key] : key"=NA") }
     {for(i=1;i<=NF;++i) if(match($i,"=")) a[substr($i,1,RSTART-1)]=$i}
     { print lookup("user"),lookup("group"),lookup("start"),lookup("end") }
     { delete a }' file
0 голосов
/ 09 мая 2019

Если вы в порядке с Perl.Проверьте решение ниже:

perl -lane 'for(@F){$a.=" ".$_ if(/user=|start=|end=|group=/)}print $a;undef $a' your_file
0 голосов
/ 09 мая 2019

Пожалуйста, попробуйте следующее:

awk '
BEGIN {f["user"] = f["group"] = f["start"] = f["end"] = 1}
{for (i=1; i<=NF; i++) {
    split($i, a, "=")
    if (f[a[1]]) printf("%s ", $i)
 }
print ""
}' filename

Уродливая точка - каждая строка содержит дополнительный пробел в конце строки.
Надеюсь, это поможет.

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