Есть ли способ преобразовать абзацы в столбцы в сценарии оболочки для форматирования в Excel? - PullRequest
3 голосов
/ 19 июня 2019

У нас есть требование к форматированию данных, представленных в формате списка, в файл CSV

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

ORG MANAGER
  No ORG MANAGER found

BILLING MANAGER
  No BILLING MANAGER found

ORG AUDITOR
 xxx
 yyy
 zzz
 aaa
 bbb
 ccc

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

ORG MANAGER               BILLING MANAGER               ORG AUDITOR
No ORG MANAGER found      No BILLING MANAGER found      xxx
                                                        yyy
                                                        zzz
                                                        aaa
                                                        bbb
                                                        ccc

Я разбил каждый абзац, сохранил его в отдельных файлах и попытался распечатать их с помощью команды paste -d '\t\t, как показано ниже:

paste -d "\t\t\t" file1 file2 file3 > fin.csv

После этого я попытался отформатировать вывод, используя следующую команду:

awk '{ $NF = "\t" $NF; print }' fin.csv | column -t -s $'\t'

Но результат не такой, как я ожидал.

paste -d "\t\t\t" file1 file2 file3 > fin.csv  --> to print the files side by side 

awk '{ $NF = "\t" $NF; print }' fin.csv | column -t -s $'\t' --> to format

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

Я добавляю ожидаемый формат ввода и вывода в прилагаемую оснастку для ясного понимания.

Ответы [ 3 ]

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

Это легко сделать с помощью awk,

awk 'BEGIN{RS=""; FS="\n"; OFS=","; ORS="\n"}
     { for (i=1;i<=NF;++i) {c[FNR,i]=$i; sub(/^[[:blank:]]*/,"",c[FNR,i])} }
     { nf_max= (NF>nf_max?NF:nf_max) }
     END{ for(j=1;j<=nf_max;++j) {
             for(i=1;i<=FNR;++i) { printf ("%s" (i==FNR?ORS:OFS)), c[i,j] }
          }
     }' file

Это выведет CSV следующего формата:

ORG MANAGER,BILLING MANAGER,ORG AUDITOR
No ORG MANAGER found,No BILLING MANAGER found,xxx
,,yyy
,,zzz
,,aaa
,,bbb
,,ccc

Как это работает?

  • Говоря awk, чтобы установить разделитель записей RS на пустую строку, мы определяем каждую запись как блок текста, разделенный пустой строкой.
  • Каждое поле в этой записи разделено символом новой строки.
  • Мы сохраняем каждое поле в массиве, который индексируется номером записи FNR и номером поля. Таким образом, мы можем полностью восстановить файл CSV.
  • Поскольку вам нужен файл CSV, мы устанавливаем разделитель выходного поля OFS как символ , а разделитель выходной записи, который теперь является строками, - как символ .
  • Мы отслеживаем максимальное количество полей в записи, которое указывает максимальное количество строк в файле CSV.
  • Если у поля меньше максимального количества полей, мы все равно можем запросить содержимое этого поля из нашего массива, так как по умолчанию awk выводит строковые значения в пустое.

Ваш вопрос изначально задавался для файла CSV, но вы запросили файл TSV, который выровнен. Мы могли бы расширить вышеприведенную команду awk для этого, но было бы проще просто проанализировать полный вывод с помощью команды column:

$ awk ... file | column -s, -o $'\t' -t
ORG MANAGER             BILLING MANAGER                 ORG AUDITOR
No ORG MANAGER found    No BILLING MANAGER found        xxx
                                                        yyy
                                                        zzz
                                                        aaa
                                                        bbb
                                                        ccc

Вы можете использовать cat, чтобы ожидать, что поля корректируются с пробелами, соответствующими ширине, и между полями вставляется только одна вкладка:

$ awk ... file | column -s, -o $'\t' -t | cat -vET
ORG MANAGER         ^IBILLING MANAGER         ^IORG AUDITOR$
No ORG MANAGER found^INo BILLING MANAGER found^Ixxx$
                    ^I                        ^Iyyy$
                    ^I                        ^Izzz$
                    ^I                        ^Iaaa$
                    ^I                        ^Ibbb$
                    ^I                        ^Iccc$
0 голосов
/ 19 июня 2019

Вот еще один awk скрипт.

/^[[:space:]]*$/{  # column separator
    maxRow = (rowCount > maxRow) ? rowCount : maxRow; # find maxRows
    rowCount = 0; # reset rows count
    columnCount++; # increment columns count
    next;         # skip inclusion in cells
}
{  cells[(columnCount + 1)","++rowCount] = $0; } # read each input row as cell
END {
    maxRow = (rowCount > maxRow) ? rowCount : maxRow; # ind maxRows (including last column)
    columnCount++; # increment last column read (suming no new line termination)
    for (row = 1; row <= maxRow; row++) {  # print out each row
        printf("%s", cells[1","row]);     # print out the first element in row
        for (col = 2; col <= columnCount; col++) {
            printf("\t%s", cells[col","row]); # print , delimiter for each element in row
        }
        printf("\n");                    # terminate each row with newline
    }
}

Выходные данные с разделителями табуляции CSV:

ORG MANAGER     BILLING MANAGER ORG AUDITOR
  No ORG MANAGER found    No BILLING MANAGER found       xxx
                 yyy
                 zzz
                 aaa
                 bbb
                 ccc

Вы можете добавить столько столбцов, сколько необходимо.

команда выполнения:

 awk -f script.awk input.txt > output.csv

Для редактирования с помощью micorsoft-excell или libreOffice-cals. Откройте новый лист снаряжения.

Импорт данных из output.csv с использованием инструментов данных. Данные output.csv разделены табуляцией.

удачи.

0 голосов
/ 19 июня 2019

Чтобы получить выходные данные, вы можете импортировать их в Excel в виде строки ячеек:

$ awk -v RS= '{gsub(/\n +/,"\n"); printf "%s\"%s\"", s, $0; s=","} END{print ""}' file
"ORG MANAGER
No ORG MANAGER found","BILLING MANAGER
No BILLING MANAGER found","ORG AUDITOR
xxx
yyy
zzz
aaa
bbb
ccc"

Сохраните выходные данные в файл "foo.csv", дважды щелкните его в Windows, и он 'в Excel будет отображаться так, как вы хотите.

Чтобы получить результат, который вы запрашивали визуально, будет:

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

$ awk -f tst.awk file
ORG MANAGER             BILLING MANAGER                 ORG AUDITOR
No ORG MANAGER found    No BILLING MANAGER found        xxx
                                                        yyy
                                                        zzz
                                                        aaa
                                                        bbb
                                                        ccc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...