2012-05-08 4 views
1

у меня есть эти два файла: file1как сравнивать числовые поля в двух файлах с AWK

2537 

1279 

1075 

12799 

1474 

135441 

1260 

1169 

1281 

10759 

и file2

1070,1279960511,BR,USA,UNITED STATES 
1278,1279960511,US,USA,UNITED STATES 
1279,1279960527,CA,CAN,CANADA 
1289,1279967231,US,USA,UNITED STATES 
2679,1279971327,CA,CAN,CANADA 
1279,1279971839,US,USA,UNITED STATES 
1279,1279972095,CA,CAN,CANADA 
1279,1279977471,US,USA,UNITED STATES 
127997,1279977983,CA,CAN,CANADA 
127997,1279980159,US,USA,UNITED STATES 
127998,1279980543,CA,CAN,CANADA 
107599,1075995007,US,USA,UNITED STATES 
107599,1075995023,VG,VGB,VIRGIN ISLANDS, BRITISH 
107599,1075996991,US,USA,UNITED STATES 
107599,1075997071,CA,CAN,CANADA 

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

awk -F, ' 
BEGIN {FS="," ; i=1 ; while (getline < "file2") { x[i] = $1 ; y[i] = $3 ; i++ }} 

{ a[$1] = $1 ; h=1 ; while (x[h] <= a[$1]) { h++ } ; { print y[h] }}' file1 

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

Желаемый результат:

#this is a comment and i ll write file 2 as if it was a matrix 

because file1[1] > file2[1,1] ... and file1[1] > file2[2,1] .... and file1[1] > file2[3,1] ... and file1[1] > file2[4,1] but file1[1] < file2[5,1] ... then print file2[4,3] ... which is "US" 

now go to file1[2] : 

file[2] > file2[1,1] ... and file1[2] > file2[2,1] ... but file1[2] <= file2[3,1] ... then print file2[3,3] 

в заключение я хочу напечатать: «третий elemenent (Col) первой линии (от file2) элемент file1 первый становится> первый элемент следующей строки (file2)

+0

Я думаю, что вы должны иметь в виду 3-й элемент файла2? –

+0

Можете ли вы объяснить больше, что вы хотите сделать? Самое низкое число в первом списке - 1075, а во втором - 1070. Таким образом, за исключением 1070, каждая строка во втором списке квалифицирует критерии, которые вы указали. –

+0

no Я хочу только запись для «первого» совпадения или первого файла file1 [i]> file2 [j], а затем выйти из цикла и перейти к файлу1 [i + 1] «третий элемент файла 2 - это wht i означало спасибо:)) – rima

ответ

1

Длинные один лайнер:

Вот один из способов вы можете сделать это:

cat file1|grep -vE '^$'|while read min; do cat file2|while read line; do val=$(echo $line|cut -d, -f1); if [ $min -lt $val ]; then short_country=$(echo $line|cut -d, -f3); echo $min: $short_country "($val)"; break; fi; done; done 

Это дает выход

2537: CA (2679) 
1279: US (1289) 
1075: US (1278) 
12799: CA (127997) 
1474: CA (2679) 
1260: US (1278) 
1169: US (1278) 
1281: US (1289) 
10759: CA (127997) 

Пояснение

Вместо того, чтобы этот один-лайнер, это легче понять, если разбить его в скрипте:

#!/bin/bash 

cat file1 |        # read file1 
grep -E '^[0-9]+$' |      # filter out lines in file1 that don't just contain a number 
while read min; do      # for each line in file1: 
    cat file2 |        # read file2 
    grep -E '^([0-9]+,){2}[A-Z]{2},' |  # filter out lines in file2 that don't match the right format 
    while read line; do      # for each line in file2: 
    val=$(echo $line|cut -d, -f1)    # pull out $val: the first comma-delimited value 
    if [ $min -lt $val ]; then    # if it's greater than the $min value read from file1: 
     short_country=$(echo $line|cut -d, -f3) # get the $short_country from the third comma-delimited value in file2 
     echo "$min: $short_country ($val)"  # print it to stdout. You can get rid of ($val) here if you're not interested in it. 
     break          # Now that we've found a value in file2, stop this loop and go to the next line in file1 
    fi 
    done 
done 

Поскольку вы первоначально не указать выходной формат, я догадался. Надеюсь, вам это полезно.

+0

thankks do explain plzz Я все еще пытаюсь понять, что вы здесь сделали – rima

+0

Пояснение готово - сообщите нам, если у вас есть вопросы об этом –

+0

@rima: выход nimbus был например, я надеялся, что вы предоставите. Посмотрите, как легче понять ваше требование, когда отчет четко сформулирован, а не просто дополнительный текст «Мне нужно это, а затем это, а затем это и ...» :-) В будущем, пожалуйста, поймите, что вы попросив людей потратить время, чтобы помочь вам решить вашу проблему и дать четкое определение того, что вам нужно, даст вам ответ быстрее. Удачи. – shellter

1

Не можете ли вы использовать xargs для части «прочитать файл1» вашего задания? Единственная часть «seek value in file2» очень проста в awk, и вы избегаете указателей двойных файлов ...

Редактировать: пример использования xargs и awk.

cat file1 | xargs awk '$1 > ARGV[2] {print $3; return}' file2 

Edit: Этот пример работает (пробовал на моем компьютере сейчас ...)

Использование -n 1 в качестве опции для xargs пройти ровно один аргумент в каждом проходе. Удалите «val» arg после его сохранения, поэтому AWK получает только имя файла (file2) и знает, что делать. Флаг, если найден, возврат не существует.

cat file1 | xargs -n 1 awk -F, 'BEGIN {val = ARGV[2]; ARGC--; found=0} $1 > val {if (found==0) { print val, $3; found = 1}}' file2 

Edit: короткая версия

cat file1 | xargs -n 1 awk -F, 'BEGIN {val = ARGV[2]; ARGC--} (!found) && ($1 > val) {print val, $3; found = 1}' file2 

версия сценария:

#!/usr/bin/awk -f 
BEGIN { 
    val = ARGV[2] 
    ARGC-- 
} 
(!found) && ($1 <= val) { 
    # cache 3rd column of previous line 
    prev = $3 
} 
(!found) && ($1 > val) { 
    # print cached value as soon as we cross the limit 
    print val, prev 
    found = 1 
} 

имя его find_val.awk и CHMOD + х он.В общем, вы жулик просто сделать find_val.awk somefile somevalue и использование xargs так же

cat file1 | xargs -n 1 find_val.awk file2 
+0

с xargs как ?? это не единственный файл, просто образец длинного и большого количества файлов, и я знаю, что значение поиска простое и его wht я пытаюсь сделать, но все же его не работает для меня. – rima

+2

Это не ответ на его вопрос. Подобная вещь была бы более подходящей в качестве комментария. –

+0

У меня такое чувство, что OP пытается использовать неправильные инструменты для работы. Поэтому для меня это решение предлагаемой проблемы. – rewritten

2

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

#!/usr/bin/awk -f 
BEGIN { 
    FS="," 
    count = 1 
    while (getline < "file2") { 
     key[count] = $1 
     countrycode[count] = $3 
     count++ 
    } 
} 

{ 
    for (idx = 1; idx <= count; idx++) 
    { 
     if ($1 < key[idx]) { 
      print countrycode[idx] 
      next 
     } 
    } 
} 

Пример запуска (печать $0 вместо того, чтобы просто $3 - код выше только отпечатки $3):

$ sort -n -k1,1 -t, file2 > tmp; mv tmp file2 
$ ./scannums file1 
2679,1279971327,CA,CAN,CANADA 
1289,1279967231,US,USA,UNITED STATES 
1278,1279960511,US,USA,UNITED STATES 
127997,1279977983,CA,CAN,CANADA 
2679,1279971327,CA,CAN,CANADA 
1278,1279960511,US,USA,UNITED STATES 
1278,1279960511,US,USA,UNITED STATES 
1289,1279967231,US,USA,UNITED STATES 
127997,1279977983,CA,CAN,CANADA 

Обратите внимание, что ничего не печатается для значения 135441 из file1, так как ничего из file2 не отвечает критериям ,

Если вы предпочитаете, это может быть сделано в однострочный.

+0

Я действительно не понимаю, как это получается Что я могу получить, так это то, что когда $ 1 является <= ключ [indx], тогда распечатайте его. Он должен напечатать код страны для всех значений, где $ 1 удовлетворяет этому , очевидно, это не case, поэтому plzz помогите мне понять этот последний цикл – rima

+0

@rima: Пожалуйста, отредактируйте свой вопрос, чтобы показать фактический результат, который должны предоставить ваши данные образца (также укажите соответствующую полную строку из файла2, чтобы мы могли видеть, как они должны совпадать). Укажите, следует ли сортировать или сортировать файлы. Это очень сложно, чтобы следовать за вашей массивной нотации. На основании комментария, который я нашел прикрепленным к другому ответу (информация должна быть отредактирована в вопросе), я изменил свой ответ на использование '<' вместо '<=' и предположил, что файл1 не отсортирован, а файл2 отсортирован. –

2

Будет ли это работать?

sort -n -t"," -k1,1 file1 file2 | awk -F"," '{if ($3 != "") {s = $3;} else {print $1 " " s;}}' 

производит

1075 BR 
1169 BR 
1260 BR 
1279 US 
1281 US 
1474 US 
2537 US 
10759 CA 
12799 CA 
135441 CA 

Если первоначальный заказ в file1 имеет важное значение, ниже может быть использован

awk '{print NR "," $1}' file1 file2 | sort -t"," -n -k 2,2 | awk -F"," '{if ($4 != "") {s = $4;} else {print $1 " " s;}}' | sort -t"," -k1,1 | cut -d" " -f2 

производит

US 
CA 
BR 
BR 
US 
CA 
US 
BR 
CA 
US 
+0

Это на самом деле очень умно и лаконично. Мне это нравится. –

+0

1279 CA 1281 CA 10759 US 12799 CA 10759 US 135441 неизвестна мой file2 уже отсортированы в порядке возрастания его первой колонке (мой образец не которых и не должны рассматривать) мой file2 не сортируется – rima

+0

Я не Не понимаю ваш последний комментарий. –