Преобразование строк в столбцы в unix

У меня есть результат работы программы, который мне нужно преобразовать в столбцы. Я знаю, что вы можете сделать это с помощью awk или sed, но я не могу понять, как это сделать.

Вот как выглядит результат:

insert_job: aaa-bbb-ess-qqqqqqq-aaaaaa-aaaaaa   job_type: c
box_name: sss-eee-ess-saturday
command: $${qqqq-eee-eat-cmd} $${qqqq-eee-nas-cntrl-dir}\eee\CMS\CMS_C3.xml $${qqqq-eee-nas-log}\eee\AFG\AFG_Build_Qwer.log buildProcess
machine: qqqq-eee-cntl
owner: system_uu_gggg_p@ad
permission: gx,wx
condition: s(qqqq-rtl-etl-40-datamart-load-cms) & s(qqqq-eee-ess)
std_out_file: >E\:\gggg\logs\qqqq-eee-ess-saturday-cms-build.out
std_err_file: >E\:\gggg\logs\qqqq-eee-ess-saturday-cms-build.err
max_run_alarm: 420
alarm_if_fail: 1
application: qqqq-M9887

Мне нужно, чтобы это выглядело так I need it to look like this

Или вот так:

insert_job:                 job_type:   box_name:       command:        machine: 
aaa-bbb-ess-qqqqqqq-aaaaaa-aaaaaa   c       sss-eee-ess-saturday    $${qqqq-eee-eat-cmd}    qqqq-eee-cntl

insert_job:;job_type:;box_name:;command:;machine:; 
aaa-bbb-ess-qqqqqqq-aaaaaa-aaaaaa;c;sss-eee-ess-saturday;$${qqqq-eee-eat-cmd};qqqq-eee-cntl;

В основном либо уже с разделением TAB, либо в формате CSV. Спасибо за помощь

не могли бы вы подтвердить, что job_type находится в той же строке insert_job?

Lino 10.08.2018 16:26

да. Итак, я предполагаю, что сначала его нужно поместить в отдельную строку?

PFD 10.08.2018 16:37

размещение insert_job в отдельной строке может быть удобно при написании скрипта. Может быть проще

Lino 10.08.2018 16:39

Замените изображение ожидаемого вывода текстом, чтобы мы могли протестировать решение на основе предоставленных вами вводимых данных и сравнить его с ожидаемым выводом, чтобы увидеть, работает оно или нет. Четко укажите, есть ли в вашем файле только 1 запись (т.е. вы получите только 1 строку вывода), и если это не так, и в вашем вводе есть несколько записей, тогда, конечно, покажите как минимум 2 из них, чтобы мы также можем видеть, что разделяет записи.

Ed Morton 10.08.2018 16:40

Разве для этого нельзя просто использовать rs -T? Это похоже на прямую транспозицию.

Toby Speight 13.08.2018 12:22
1
5
173
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если это разовая работа, и вам не нужно беспокоиться о двойных кавычках в исходных данных, попробуйте что-нибудь вроде этого. Я предположил, что вы хотите, чтобы значения, разделенные запятыми, помещались в электронную таблицу, а данные находятся в файле с именем foo.txt.

echo $(sed 's/^\([^:]*\): \(.*\)$/"\1",/g' foo.txt)
echo $(sed 's/^\([^:]*\): \(.*\)$/"\2",/g' foo.txt)

При этом не будет печататься заголовок столбца job_type, и он будет обрабатывать текст job_type: c, как если бы он был частью данных insert_job, и добавит запятую в конце. Он также будет неправильно вести себя при различных входных значениях, таких как подстановка символов.

Ed Morton 10.08.2018 17:08
Ответ принят как подходящий

Вы не показали нам, как выглядит фактический ожидаемый результат, поэтому я предположил, что вы хотите, чтобы он был разделен табуляцией и не заключался в кавычки, и я сделал некоторые другие предположения о том, как разделяются ваши входные записи и т.д .:

$ cat tst.awk
BEGIN { OFS="\t" }
{
    if ( numTags == 0 ) {
        tag = $1
        val = $2
        sub(/:$/,"",tag)
        tags[++numTags] = tag
        tag2val[tag] = val
        sub(/[^:]+: +[^ ]+ +/,"")
    }
    tag = val = $0
    sub(/: .*/,"",tag)
    sub(/[^:]+: /,"",val)
    tags[++numTags] = tag
    tag2val[tag] = val
}
tag == "application" {
    if ( !cnt++ ) {
        for (tagNr=1; tagNr<=numTags; tagNr++ ) {
            tag = tags[tagNr]
            printf "%s%s", tag, (tagNr<numTags ? OFS : ORS)
        }
    }
    for (tagNr=1; tagNr<=numTags; tagNr++ ) {
        tag = tags[tagNr]
        val = tag2val[tag]
        printf "%s%s", val, (tagNr<numTags ? OFS : ORS)
    }
    numTags = 0
}

.

$ awk -f tst.awk file
insert_job      job_type        box_name        command machine owner   permission      condition       std_out_file    std_err_file    max_run_alarm   alarm_if_fail   application
aaa-bbb-ess-qqqqqqq-aaaaaa-aaaaaa       c       sss-eee-ess-saturday    $${qqqq-eee-eat-cmd} $${qqqq-eee-nas-cntrl-dir}\eee\CMS\CMS_C3.xml $${qqqq-eee-nas-log}\eee\AFG\AFG_Build_Qwer.log buildProcess qqqq-eee-cntl   system_uu_gggg_p@ad    gx,wx    s(qqqq-rtl-etl-40-datamart-load-cms) & s(qqqq-eee-ess)  >E\:\gggg\logs\qqqq-eee-ess-saturday-cms-build.out      >E\:\gggg\logs\qqqq-eee-ess-saturday-cms-build.err      420     1       qqqq-M9887

Если вы хотите, чтобы Excel обрабатывал что-то более простое, это создаст CSV, который Excel сможет открыть, просто дважды щелкнув имя выходного файла:

$ cat tst.awk
BEGIN { OFS="," }
{
    if ( numTags == 0 ) {
        tag = $1
        val = $2
        sub(/:$/,"",tag)
        tags[++numTags] = tag
        tag2val[tag] = val
        sub(/[^:]+: +[^ ]+ +/,"")
    }
    tag = val = $0
    sub(/: .*/,"",tag)
    sub(/[^:]+: /,"",val)
    tags[++numTags] = tag
    tag2val[tag] = val
}
tag == "application" {
    if ( !cnt++ ) {
        for (tagNr=1; tagNr<=numTags; tagNr++ ) {
            tag = tags[tagNr]
            printf "\"%s\"%s", tag, (tagNr<numTags ? OFS : ORS)
        }
    }
    for (tagNr=1; tagNr<=numTags; tagNr++ ) {
        tag = tags[tagNr]
        val = tag2val[tag]
        printf "\"%s\"%s", val, (tagNr<numTags ? OFS : ORS)
    }
    numTags = 0
}

.

$ awk -f tst.awk file
"insert_job","job_type","box_name","command","machine","owner","permission","condition","std_out_file","std_err_file","max_run_alarm","alarm_if_fail","application"
"aaa-bbb-ess-qqqqqqq-aaaaaa-aaaaaa","c","sss-eee-ess-saturday","$${qqqq-eee-eat-cmd} $${qqqq-eee-nas-cntrl-dir}\eee\CMS\CMS_C3.xml $${qqqq-eee-nas-log}\eee\AFG\AFG_Build_Qwer.log buildProcess","qqqq-eee-cntl","system_uu_gggg_p@ad","gx,wx","s(qqqq-rtl-etl-40-datamart-load-cms) & s(qqqq-eee-ess)",">E\:\gggg\logs\qqqq-eee-ess-saturday-cms-build.out",">E\:\gggg\logs\qqqq-eee-ess-saturday-cms-build.err","420","1","qqqq-M9887"

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

PFD 10.08.2018 17:14

Нет, это не так и нет. Сценарий не заботится о пробелах внутри полей, поле - это поле, независимо от того, содержит ли оно пробелы или нет, и все поля отделены табуляцией от других полей. Единственная проблема, с которой вы столкнетесь с выводом, будет, если ваши поля уже содержат табуляции, а затем вы просто измените OFS = "\ t" на любой символ, который вы хотите использовать в качестве разделителя поля вывода.

Ed Morton 10.08.2018 17:18

Хорошо, я вижу. Можно ли разделить его табуляцией, чтобы я мог легко разделить его в Excel? Прямо сейчас есть одиночные пробелы, поэтому я подумал, что произошла ошибка, когда я пытался преобразовать данные в столбцы в Excel.

PFD 10.08.2018 17:22

Как я уже упоминал, вывод ЯВЛЯЕТСЯ разделен табуляцией. Похоже, вы изо всех сил пытаетесь использовать Excel с данными, разделенными табуляцией (что сложно, учитывая весь интерфейс импорта данных, который они необъяснимо реализовали). Обратитесь к документации Excel, чтобы узнать, как импортировать файлы с разделителями табуляции.

Ed Morton 10.08.2018 17:25

Даже если я вставлю в простой блокнот, я вижу, что между "insert_job" и "job_type" есть 6 пробелов.

PFD 10.08.2018 17:27

Я понятия не имею, как копирование / вставка работает на вашем компьютере / буфере обмена / блокноте, но, видимо, когда вы это делаете, он преобразует вкладки, которые выводит инструмент, в пустые символы. Вывод просто разделен табуляцией, вот и все. Вы можете видеть OFS="\t" - никакого волшебства не происходит, это ЯВЛЯЕТСЯ как разделитель выходных полей. Я добавил версию, которая будет создавать CSV, такой как Excel, вероятно, будет доволен (если у вас нет данных, которые Excel считает датой - тогда нам придется добавить дополнительный код, чтобы справиться с этим). Вот почему так важно, когда вы публикуете вопрос, включать точно текстовый вывод, который вы хотите получить.

Ed Morton 10.08.2018 17:31

Если вы хотите узнать больше о проблеме преобразования полей Excel, которые, по его мнению, могут быть датами, в фактические даты (например, он может преобразовать число типа «1,3» в дату типа «Январь-3»), см. stackoverflow.com/questions/165042/…, но я не Я не вижу очевидных случаев, когда это могло бы произойти с образцами данных, которые вы уже предоставили.

Ed Morton 10.08.2018 17:35

Другая проблема, с которой я столкнулся, - когда я запускаю скрипт, я получаю следующую ошибку: awk: синтаксическая ошибка около строки 6 awk: незаконный оператор около строки 6

PFD 10.08.2018 17:40

Вы пытаетесь запустить старый сломанный awk (/ bin / awk в Solaris). Никогда не используйте эту awk. В Solaris используйте / usr / xpg6 / bin / awk вместо (или ... / xpg4 / ...).

Ed Morton 10.08.2018 17:42

Погодите - если вы получаете синтаксическую ошибку, значит, вы не смогли запустить скрипт, так что это было за предыдущее обсуждение того, что он производит неправильный вывод ???

Ed Morton 10.08.2018 17:44

Я скопировал результат, который вы предоставили для тестирования, и в нем было 6 пробелов. Вроде работает с xpg4, остальное сейчас протестирую и дам знать

PFD 10.08.2018 17:54

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

Ed Morton 10.08.2018 18:03

@EdMorton, Вы являются святой ;-) Всем удачи.

shellter 10.08.2018 18:35

@EdMorton, спасибо! Работает. Я заметил одну вещь: там написано: tag == "application" {:, ищет ли он это конкретное слово? Что делать, если последняя строка не «приложение»?

PFD 10.08.2018 19:28

1) Да. 2) Тогда нам нужно будет использовать что-то еще, чтобы идентифицировать конец или начало записей, поэтому мой комментарий под вашим вопросом, когда я говорю if ... there's multiple records in your input then, of course, show at least 2 of them so we can see what separates the records too.

Ed Morton 10.08.2018 22:16

Насколько я могу судить, существует как минимум 2 разных случая, один из которых - «приложение», а другой - «alarm_if_fail». Могут быть и другие, о которых я тоже не знаю. Есть ли способ остановить это, не зная конечного слова?

PFD 10.08.2018 23:18

Да, есть несколько возможностей, но я не могу предложить ни одну из них, не увидев, как на самом деле выглядит ваш ввод с несколькими записями. Еще раз: if ... there's multiple records in your input then, of course, show at least 2 of them so we can see what separates the records too.

Ed Morton 11.08.2018 07:45

Другие вопросы по теме