Разделить столбец на несколько на основе совпадения / разделителя с помощью bash awk - PullRequest
0 голосов
/ 14 мая 2018

У меня есть набор данных в одном столбце, который я хотел бы разделить на любое количество новых столбцов, когда найдена определенная строка (в данном случае 'male_position'.

>cat test.file

male_position
0.00
0.00
1.05
1.05
1.05
1.05
3.1
5.11
12.74
30.33
40.37
40.37
male_position
0.00
1.05 
2.2
4.0
4.0
8.2
25.2
30.1
male_position
1.0
5.0

Я хотел быскрипт для создания новых столбцов, разделенных табуляцией, каждый раз, когда встречается 'male_position', но просто печатайте каждую каждую строку / точку данных ниже этой (добавленной в этот столбец) до следующего появления 'male_position':

script.awk test.file > output

0.00  0.00  1.0
0.00  1.05  5.0
1.05  2.2
1.05  4.0
1.05  4.0
1.05  8.2
3.1  25.2
5.11 30.1
12.74
30.33
40.37
40.37

Anyидеи?

обновление - я пытался адаптировать код на основе этого поста ( Linux разделил столбец на два разных столбца в одном файле CSV )

cat script.awk

BEGIN {
   line = 0; #Initialize at zero
}
/male_position/ { #every time we hit the delimiter
   line = 0; #resed line to zero
}
!/male_position/{ #otherwise
   a[line] = a[line]" "$0; # Add the new input line to the output line
   line++; # increase the counter by one
}
END {
   for (i in a )
      print a[i] # print the output
}

Результаты ....

$ awk -f script.awk test.file
 1.05 2.2
 1.05 4.0
 1.05 4.0
 1.05 8.2
 3.1 25.2
 5.11 30.1
 12.74
 30.33
 40.37
 40.37
 0.00 0.00 1.0
 0.00 1.05  5.0

ОБНОВЛЕНИЕ 2 #######

Я могу воссоздать ожидаемое в случае test.file.Запуск скрипта (script.awk) в Linux с тестовым файлом и «awk.script» (см. Выше), похоже, работал. Однако этот простой файл примера имеет только уменьшающееся количество столбцов (точек данных) между разделителем (male_position).Когда вы увеличиваете номер столбцамежду ними вывод кажется неудачным ...

cat test.file2

male_position
0.00
0.00
1.05
1.05
1.05
1.05
3.1
5.11
12.74
male_position
0
5
10
male_position
0
1
2
3
5

awk -f script.awk test.file2

0.00 0 0
0.00 5 1
1.05 10 2
1.05 3
1.05 5
1.05 
3.1
5.11
12.74

нет «заполнения» строк после последнего наблюдения для данного столбца, поэтому столбец с большим количеством значений, чем предыдущий столбец, имеетего значения соответствуют предыдущему столбцу (3 и 5 находятся в столбце 2, когда они должны быть в столбце 3).

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

После awk может помочь вам в том же.

awk '/male_position/{count++;max=val>max?val:max;val=1;next} {array[val++,count]=$0} END{for(i=1;i<=max;i++){for(j=1;j<=count;j++){printf("%s%s",array[i,j],j==count?ORS:OFS)}}}' OFS="\t"   Input_file

Теперь добавляем не-лайнерную форму решения.

awk '
/male_position/{
  count++;
  max=val>max?val:max;
  val=1;
  next}
{
  array[val++,count]=$0
}
END{
  for(i=1;i<=max;i++){
      for(j=1;j<=count;j++){   printf("%s%s",array[i,j],j==count?ORS:OFS)   }}
}
' OFS="\t"   Input_file
0 голосов
/ 14 мая 2018

Вот решение csplit+paste

$ csplit --suppress-matched -zs test.file2 /male_position/ {*}
$ ls
test.file2  xx00  xx01  xx02
$ paste xx*
0.00    0   0
0.00    5   1
1.05    10  2
1.05        3
1.05        5
1.05        
3.1     
5.11        
12.74       

С man csplit

csplit - разбить файл на разделы, определяемые строками контекста

-z, --elide-empty-files удалить пустые выходные файлы

-s, --quiet, --silent не печатать счетчики размеров выходных файлов

- сопоставить подавить подавить строкиСоответствующий PATTERN

  • /male_position/ - это регулярное выражение, используемое для разделения входного файла *
  • {*} указывает на создание максимально возможного количества разбиений
  • use-f и -n опции для изменения имен выходных файлов по умолчанию
  • paste xx* для вставки файлов по столбцам, TAB является разделителем по умолчанию
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...