Как отправить отмеченные группы текста в разные столбцы в CSV в awk? - PullRequest
0 голосов
/ 30 июня 2019

У меня есть файл, помеченный как этот, с "**", помещенным в начале строки, чтобы указать новую группу текста. Это было напечатано на очень старом оборудовании, которое не поддерживает электронные таблицы:

**1**
This is some text.
This text goes with the text above.
Here is more text in the first group.
**2**
This is some other text, but in a different group.
This text ought to go in the 2nd column of the CSV.
**3**
Here is data that goes in the 3rd column.

Мне нужно отправить каждую группу текста в отдельный столбец в CSV. Поскольку запятые используются, я использую "@" в качестве разделителя.

Пример вывода:

**1**@**2**@**3**
This is some text.@This is some other text, but in a different group.@Here is data that goes in the 3rd column.
This text goes with the text above.@This text ought to go in the 2nd column of the CSV.@
Here is more text in the first group.@@

Я могу использовать AWK для перехода от приведенного ниже текста к первому, например ::10000

awk -F"@" '{ print $1 }' >> file.txt
awk -F"@" '{ print $2 }' >> file.txt
awk -F"@" '{ print $3 }' >> file.txt

Можно ли использовать awk, чтобы изменить это?

Ответы [ 3 ]

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

Поскольку может существовать еще одна группа записей:

...
**4**
foo1
foo2
foo3
foo4
foo5

, в которой больше записей, чем в первой группе, необходимо выполнить два прохода для данных, чтобы определить максимальное количество полей дляполучить право @ s или сохранить данные в массив.Я выбрал массивы и использовал GNU awk и двухмерный массив:

$ gawk '
/^\*\*/ {
    r=1
    f++
}
{
    a[r++][f]=$0
}
END {
    for(i=1;(i in a);i++)
        for(j=1;j<=f;j++)
            printf "%s%s",a[i][j],(j==f?ORS:"@")
}' file

Вывод:

**1**@**2**@**3**
This is some text.@This is some other text, but in a different group.@Here is data that goes in the 3rd column.
This text goes with the text above.@This text ought to go in the 2nd column of the CSV.@
Here is more text in the first group.@@

Вывод с моей дополнительной 4-й группой во входном файле:

**1**@**2**@**3**@**4**
This is some text.@This is some other text, but in a different group.@Here is data that goes in the 3rd column.@foo1
This text goes with the text above.@This text ought to go in the 2nd column of the CSV.@@foo2
Here is more text in the first group.@@@foo3
@@@foo4
@@@foo5
2 голосов
/ 30 июня 2019

Тот же подход, что и у @JamesBrown (поэтому, пожалуйста, оставьте его ответ принятым), но он будет работать в любом awk, и IMHO использует более понятные имена и синтаксис переменных:

$ cat tst.awk
BEGIN { OFS="@" }
/^\*\*/ {
    numCols++
    rowNr = 0
}
{
    vals[++rowNr,numCols] = $0
    numRows = (numRows > rowNr ? numRows : rowNr)
}
END {
    for (rowNr=1; rowNr<=numRows; rowNr++) {
        for (colNr=1; colNr<=numCols; colNr++) {
            printf "%s%s", vals[rowNr,colNr], (colNr < numCols ? OFS : ORS)
        }
    }
}

$ awk -f tst.awk file
**1**@**2**@**3**
This is some text.@This is some other text, but in a different group.@Here is data that goes in the 3rd column.
This text goes with the text above.@This text ought to go in the 2nd column of the CSV.@
Here is more text in the first group.@@
1 голос
/ 30 июня 2019

Не могли бы вы попробовать следующее.

awk '
BEGIN{
  OFS="@"
}
/^\*\*/{
  flag=1
  header=(header?header OFS:"")$0
  if(value){
      value=value ORS}
      next
}
{
  if(flag){
      ofs=""
  }
  else{
      ofs="@"
  }
  flag=""
  value=(value?value ofs:"")$0
}
END{
  print header ORS value"@@"
}'   Input_file
...