Реорганизация именованных полей с помощью AWK - PullRequest
1 голос
/ 29 июня 2010

Мне приходится иметь дело с различными входными файлами с несколькими полями, произвольно расположенными, но все последовательно именуемыми и помеченными строкой заголовка. Эти файлы должны быть переформатированы так, чтобы все нужные поля были в определенном порядке, с несущественными полями, удаленными и пропущенными полями. Я надеялся использовать AWK, чтобы справиться с этим, так как это помогло мне, когда имело дело с дилеммами, связанными с полем в прошлом.

После небольшого перебора я получил нечто похожее на следующее ( запись из памяти, не проверено ):

# imagine a perfectly-functional BEGIN {} block here

NR==1 {
  fldname[1] = "first_name"
  fldname[2] = "last_name"
  fldname[3] = "middle_name"
  maxflds = 3

  # this is just a sample -- my real script went through forty-odd fields

  for (i=1;i<=NF;i++) for (j=1;j<=maxflds;j++) if ($i == fldname[j]) fldpos[j]=i
}

NR!=1 {
  for (j=1;j<=maxflds;j++) {
    if (fldpos[j]) printf "%s",$fldpos[j]
    printf "%s","/t"
  }
  print ""
}

Теперь это решение отлично работает . Я запускаю его, я получаю вывод именно так, как я хочу. Нареканий нет. Тем не менее, для чего-то длиннее, чем три поля или около того (например, сорок с лишним полей, с которыми мне приходилось работать), это очень болезненно избыточный код, который всегда имеет и всегда будет беспокоить меня. И мысль о необходимости вставить поле где-то еще в этот беспорядок заставляет меня содрогаться.

Я умираю немного внутри каждый раз, когда смотрю на это.

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

Есть идеи?

1 Ответ

0 голосов
/ 29 июня 2010

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

BEGIN {while ((getline < "fieldfile") > 0) fldname[++maxflds] = $0}

Вы все равно прочитаете строку заголовка так же, как сейчас, конечно.Однако мне приходит в голову, что вы можете использовать ассоциативный массив и сократить вложенные циклы for до одного цикла for.Что-то вроде (не проверено):

BEGIN {while ((getline < "fieldfile") > 0) fldname[$0] = ++maxflds}

NR==1 {
    for (i=1;i<=NF;i++) fldpos[i] = fldname[$i]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...