Как заменить строки на несколько столбцов - PullRequest
0 голосов
/ 11 ноября 2019

Я обрабатываю большой файл mbox, чтобы проанализировать почтовый трафик info@acme.com. Файл уже в CSV с 11 столбцами. Количество необходимых замен большое (> 25), и оно прекрасно работает с функцией àwk gsub`. Но я только что понял, что замена должна выполняться только для столбцов $ 3, $ 7 и $ 9, и я хотел бы найти оптимальное решение для этого.

CSV-файл с разделителями;Между разделителями может появиться новая строка. Обычно символ новой строки внутри поля обозначается ?= в конце строки и =? в начале следующей строки, например, это строка заголовков, пустая строка и одна строка данных:

Message-ID;X-GM-THRID;X-Gmail-Labels;X-Google-Original-Date;Date;From;To;Subject;X-Spam-Flag;HasAttachment;AttachmentNames

<01a201d59317$3457d540$9d077fc0$@sbb.us>;1649279601489016232;"=?UTF-8?Q?Archived,Important,Opened,Category_?=
=?UTF-8?Q?Personal,kupci/cb-ac,naro=C4=8Dila-kupcev?=";;Mon, 4 Nov 2019 14:53:14 +0100;<bill.zeit@fgr.us>;=?iso-8859-2?Q?acme_naro=E8ilo?= <info@acme.us>;=?iso-8859-2?Q?NARO=C8ILO_7209661?=;;True;ACME 7096_2019.pdf

Моя задача - очистить данные. В частности, строка выше должна выглядеть так:

Message-ID;X-GM-THRID;X-Gmail-Labels;X-Google-Original-Date;Date;From;To;Subject;X-Spam-Flag;HasAttachment;AttachmentNames

01a201d59317$3457d540$9d077fc0$@sbb.us;1649279601489016232;Archived,Important,Opened,Category Personal,kupci/cb-ac,naročila-kupcev;;Mon, 4 Nov 2019 14:53:14 +0100;bill.zeit@fgr.us;acme naročilo info@acme.us;NAROČILO 7209661;;True;ACME 7096 2019.pdf

В настоящее время я запускаю команду:

awk -f replacements.awk email.csv > newEmail.csv

Файл replacements.awk выглядит следующим образом:

{
  gsub("_"," ");
  gsub("20="," "); 
  gsub("=?","");   
  gsub(/\?=/,"");  
  gsub("_"," ");
  gsub("<","");
  gsub(">","");
  gsub(/"/,"");
  ...
  print
 }

Мне бы хотелось, чтобы файл replacements.awk был написан так, чтобы мне не нужно было повторять операторы gsub три раза, чтобы заменить строки на три столбца.

Спасибо

Ответы [ 3 ]

1 голос
/ 11 ноября 2019
  • объединение нескольких шаблонов замены в одну комбинацию с использованием регулярного выражения группы альтернатив ..|.. или класса символов [...]
  • перемещения общих замен впользовательская функция, которая будет принимать столбец в качестве аргумента

function sub_col(col) {
    gsub(/[<>"]|\?=|=\?/, "", $col);
    gsub(/_|20=/, " ", $col);
}
{
    sub_col(3); sub_col(7); sub_col(9);  
}
1 голос
/ 11 ноября 2019

Похоже, что это может быть то, что вы хотите:

awk '
BEGIN {
    split("3 7 9", tgts)
}
{
    for (i in tgts) {
        tgt = tgts[i]
        gsub(/_|20=/," ",$tgt)
        gsub(/=\?|\?=|[<>"]/,"",$tgt)
    }
    print
}
' file

, но без выборки ввода / вывода это просто непроверенное предположение.

1 голос
/ 11 ноября 2019

Так как вы не показали образцы вашего Input_file и ожидаемого вывода, значит, не можете его протестировать. У вас есть несколько глобальных подстановок, которые либо подставляют регулярное выражение / строку в пробел ИЛИ в NULL, поэтому мы можем объединить оба.

Я объединил все регулярные выражения для пробела вместе и все регулярные выражения для NULL вместе следующим образом.

gsub(/_|20=/," ");gsub(/=\?|\\\?=|<|>|\"/,"")

Вы можете использовать | (ИЛИ) для упоминания множественного регулярного выражения в gsub. Я взял все регулярные выражения из ваших показанных сэмплов, если у вас есть еще несколько, вы можете объединить их, как я делал выше.



РЕДАКТИРОВАТЬ: Добавляя пример для удаления, выполняйте несколько операций gsub над несколькими полями, скажем, следующим является Input_file. Это всего лишь пример, вам нужно настроить его в соответствии с вашим Input_file.

cat Input_file
1 23_?=??": bla bla bla
1 23_?=??": bla bla bla
1 23_?=??": bla bla bla
1 23_?=??": bla bla bla
1 23_?=??": bla bla bla
1 23_?=??": bla bla bla
1 23_?=??": bla bla bla

Теперь следующее решение.

awk '
function remove(field){
  num=split(field,array,",")
  for(i=1;i<=num;i++){
    gsub(/=\?|\\\?=|<|>|\"/,"",$i)
  }
}
remove("2,3")
1
' Input_file

Выше я упомянул remove("2,3"), что означает, что яВызов функции с именами remove и 2,3 означает выполнение операции gsub над 2-м и 3-м полями, но это только пример замены, вам нужно настроить это в своем коде или вы можете использовать его в качестве начального шага.

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