текстовая обработка (чтение и вычисление из двух файлов)

У меня есть один текст: (слова, домены слов)

car transport car machine bank economy bank politics bank parks God religion ... 

Есть много слов, некоторые слова имеют разные домены, а у других есть только один домен. У меня есть еще один файл, огромная матрица (300 размерностей каждой строки), состоящая из слов и вектора для каждого типа:

 bank 0.9 1.5 3.2 -0.2 0.1 ... God 1.0 2.1 -0.5 0.7 ... rose 0.2 -1.8 ... ... ... 

Я хотел бы прочитать, сколько раз появляется каждое слово в первом файле и в соответствии с этим выбирают самые высокие «n» числа в каждом векторе второго файла, зная, к какому полю оно принадлежит. Что-то вроде этого:

 car 2 bank 3 God 1 

и передать эти числа в

 bank 4 3.2 bank 3 1.5 bank 2 0.9 God 3 2.1 

Первая часть, о которой я думал

 gawk 'NR==FNR {a[$1]++;next;} dont know what here?' list matrix 

Я знаю его немного сложнее, но любая помощь приветствуется. Может быть, другой способ проще?

3 Solutions collect form web for “текстовая обработка (чтение и вычисление из двух файлов)”

 awk ' NR==FNR{ #operate matrix file first A[$1] = 1 #array of words for(i=2;i<=NF;i++) B[$1 OFS i] = $i #array with indexes [word field_num] next } $1 in A{ #if word in array A max = $1 OFS 2 for(i in B) if(i ~ "^" $1 && B[max] < B[i]) max = i #find maximum in B-array print max, B[max] #output word + field_num + value delete B[max] #exclude value from next search } } ' matrix list 

Если версия awk позволяет упростить скрипт псевдо-многомерных массивов

 awk ' NR==FNR{ for(i=2;i<=NF;i++) A[$1][i] = $i next } $1 in A{ max = 2 for(i in A[$1]) if(A[$1][max] < A[$1][i]) max = i print $1, max, A[$1][max] delete A[$1][max] } } ' matrix list 

Это действительно довольно сложно. Я бы предложил создать awk скрипт, если кто-то не придумает чудо-однострочный.

Внутри вашего файла awk :

 NR==FNR { a[$1]++ next } #Your probably know what that does since it's your starting point # If first field is a key in array a $1 in a { # Assign the number of occurences of this word in variable n n=a[$1] # Initialize this value to + INFINITY k=-log(0) # Loop on the number of occurences of the word for (i=0; i<n; i++) { # Initialize max value and its index at the first value of the vector m=$2 i_m=2 # Loop on the number of fields in the matrix for that word for (j=3; j<NF+1; j++) { # Look for the largest value that stays below previous max (if none then k is INFINITY) if ($j > m && $j < k) { m=$j; i_m=j } } # Print the word, the index of its max and its value printf $1" "i_m" "m"\n" # Store the max to be able to scan for the next biggest number at next iteration k=m } } 

Чтобы запустить его:

 $ awk -f myScript.awk list matrix 

Мой скрипт, похоже, работает нормально, за исключением одного случая: если в list есть равное число или больше вхождений слова, чем в его векторе в matrix есть значения. Это не похоже на проблему, так как ваши векторы довольно большие. И инициализация k at -log(0) чтобы получить ее значение inf , немного странно, но я не мог понять, как установить ее непосредственно в inf ( =inf не работает явно). Возможно, вы можете обработать больше случаев (если у вас есть одно и то же значение несколько раз в вашем векторе, например …), но я оставлю его вам, поскольку у вас есть начальная точка сейчас!

TXR Lisp с макросом awk :

 (let ((h (hash :equal-based))) (awk (:inputs "word-dom-pairs") (t (inc [h [f 0] 0]))) (awk (:inputs "word-vectors") (t (whenlet ((count [h [f 0]])) (fconv - : r) (let* ((n-fn-pairs (zip (rest f) (range 2))) (n-fn-sorted [sort n-fn-pairs > first])) (each ((p [n-fn-sorted 0..count])) (prn [f 0] (second p) (first p)))))))) 

Бег:

 $ txr munge.tl bank 4 3.2 bank 3 1.5 bank 2 0.9 God 3 2.1 

Данные:

 $ cat word-dom-pairs car transport car machine bank economy bank politics bank parks God religion $ cat word-vectors bank 0.9 1.5 3.2 -0.2 0.1 God 1.0 2.1 -0.5 0.7 rose 0.2 -1.8 

Ниже приведена версия программы, развернутая в одно выражение awk :

 (awk (:inputs "word-dom-pairs" "word-vectors") (:let (h (hash :equal-based))) ((= arg 1) (inc [h [f 0] 0])) ((= arg 2) (whenlet ((count [h [f 0]])) (fconv - : r) (let* ((n-fn-pairs (zip (rest f) (range 2))) (n-fn-sorted [sort n-fn-pairs > first])) (each ((p [n-fn-sorted 0..count])) (prn [f 0] (second p) (first p))))))) 

Два :inputs от ранее выделенных awk -s объединяются в один. Мы заменяем безусловные истинные шаблоны t селекторами, на основе которых обрабатывается ввод данных переменной arg . Функция let которая связывает переменную хеш-таблицы, складывается в макрос awk :let clause.

Если мы удалим предложение (:inputs ...) , мы можем предоставить файлы, используя пару аргументов командной строки:

 $ txr munge.tl file1 file2 

TXR Lisp – это безопасный тип, динамический язык, в котором переменные должны быть определены до назначения или использования. Необязательные переменные и нежелательные строки не являются числовым нулем, а строки, которые выглядят как числа, не являются числами. Вот почему мы явно определяем существование хэш-таблицы и используем fconv для явного преобразования второго и последующих полей в действительные числа ( r ).

  • Как исключить строки, которые не содержат строку из вывода скрипта awk?
  • Преобразование строки в метку времени даты в gawk или awk
  • Переносная проверка массива
  • инструменты редактирования потока: вывод, что очищается
  • неуклюжую работу убивают, слишком большой вклад?
  • Есть ли какой-либо другой способ раскола в awk?
  • Как добавить / добавить временную метку для вывода grep?
  • awk найти строки с двумя совпадениями
  • gawk с gawkextlib
  • Пропустить первые 6 строк / строк в текстовом файле с помощью awk
  • Самый эффективный способ сделать полмиллиона операций математики ежечасно
  • Linux и Unix - лучшая ОС в мире.