Извлечь последовательность из списка данных в отдельную строку - PullRequest
1 голос
/ 28 февраля 2020

sample.txt действительно имеет «столбец, разделенный табуляцией», и есть semi-colon seperated, который необходимо соответственно разделить из последовательности чисел на повторяющееся значение.

cat sample.txt

2   2627    588;577
2   2629    566
2   2685    568-564
2   2771    573
2   2773    597
2   2779    533
2   2799    558
2   6919    726;740-742;777
2   7295    761;771-772

Обратите внимание, что некоторые из строка может иметь перевернутую последовательность 568-564 Используя предыдущий скрипт, мне удалось ее разбить, но не удалось извлечь из последовательности (разбитую по da sh)

#!/bin/sh
awk -F"\t" '{print $1}' $1 >> $2 && 
awk -F"\t" '{print $2}' $1 >> $2 && 
awk -F"\t" '{print $3}' $1 >> $2 &&
sed -i "s/^M//;s/;\r//g" $2
#!/bin/awk -f
BEGIN { FS=";"; recNr=1}
!NF { ++recNr; lineNr=0; next }
{ ++lineNr }
lineNr == 1 { next }
recNr == 1  { a[lineNr] = $0 }
recNr == 2  { b[lineNr] = $0 }
recNr == 3  {
    for (i=1; i<=NF; i++) {
        print a[lineNr] "," b[lineNr] "," $i
    }
}

Ожидается

2,2627,588
2,2627,577
2,2629,566
2,2685,564
2,2685,565
2,2685,566
2,2685,567
2,2685,568
2,2771,573
2,2773,597
2,2779,533
2,2799,558
2,6919,726
2,6919,740
2,6919,741
2,6919,742
2,6919,777
2,7295,761
2,7295,771
2,7295,772

Ответы [ 2 ]

2 голосов
/ 28 февраля 2020

Не могли бы вы попробовать следующее (добавим объяснение через несколько минут).

awk '
BEGIN{
  OFS=","
}
{
  num=split($NF,array,";")
  for(i=1;i<=num;i++){
    if(array[i]~/-/){
      split(array[i],array2,"-")
      to=array2[1]>array2[2]?array2[1]:array2[2]
      from=array2[1]<array2[2]?array2[1]:array2[2]
      while(from<=to){
        print $1,$2,from++
      }
    }
    else{
      print $1,$2,array[i]
    }
    from=to=""
  }
}
'   Input_file

Объяснение: Добавление подробного объяснения для приведенного выше кода.

awk '                                                  ##Starting awk program from here.
BEGIN{                                                 ##Starting BEGIN section of code here.
  OFS=","                                              ##Setting OFS as comma here.
}
{
  num=split($NF,array,";")                             ##Splitting last field of line into an array named array with delimiter semi-colon here.
  for(i=1;i<=num;i++){                                 ##Starting a for loop from 1 to till value of num which is actually length of array created in previous step.
    if(array[i]~/-/){                                  ##Checking condition if array value with index i is having dash then do followong.
      split(array[i],array2,"-")                       ##Split value of array with index i to array2 here with delimiter -(dash) here.
      to=array2[1]>array2[2]?array2[1]:array2[2]       ##Creating to variable which will compare 2 elements of array2 and have maximum value out of them here.
      from=array2[1]<array2[2]?array2[1]:array2[2]     ##Creating from variable which will compare 2 elements of array2 and will have minimum out of them.
      while(from<=to){                                 ##Running while loop from variable from to till value of variable to here.
        print $1,$2,from++                             ##Printing 1st, 2nd fields with value of from variable and increasing from value with 1 each time it comes here.
      }
    }
    else{                                              ##Mention else part of if condition here.
      print $1,$2,array[i]                             ##Printing only 1st, 2nd fields along with value of array with index i here.
    }
    from=to=""                                         ##Nullifying variables from and to here.
  }
}
'  Input_file                                          ##Mentioning Input_file name here.

Добавление ссылки для условных операторов ? и : объяснение в соответствии с комментариями Джеймса сэра:

https://www.gnu.org/software/gawk/manual/html_node/Conditional-Exp.html

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

2,2627,588
2,2627,577
2,2629,566
2,2685,564
2,2685,565
2,2685,566
2,2685,567
2,2685,568
2,2771,573
2,2773,597
2,2779,533
2,2799,558
2,6919,726
2,6919,740
2,6919,741
2,6919,742
2,6919,777
2,7295,761
2,7295,771
2,7295,772
1 голос
/ 28 февраля 2020
$ awk '
BEGIN {
    FS="( +|;)"             # input field separator is space or ;
    OFS=","                 # output fs is comma
}
{
    for(i=3;i<=NF;i++) {    # from the 3rd field to the end
        n=split($i,t,"-")   # split on - if any. below loop from smaller to greater
        if(n)               # in case of empty fields
            for(j=(t[1]<t[n]?t[1]:t[n]); j<=(t[1]<t[n]?t[n]:t[1]);j++)
                print $1,$2,j   # output
    }
}' file

Выход

2,2627,588
2,2627,577
2,2629,566
2,2685,564   <─┐
2,2685,565     │
2,2685,566     ├─ wrong order, from smaller to greater
2,2685,567     │
2,2685,568   <─┘
2,2771,573
2,2773,597
2,2779,533
2,2799,558
2,6919,726
2,6919,740
2,6919,741
2,6919,742
2,6919,777
2,7295,761
2,7295,771
2,7295,772

Протестировано на GNU awk, mawk, Busybox awk и awk версии 20121220.

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