2015-12-23 3 views
2

Я пытаюсь сравнить столбцы в двух разных файлах (1-ый из proba2.dat с 2 из proba1.dat), бывшегоAWK копирования столбцов с несколькими условиями

proba1.dat 
1 -3.56 
2 -3.40 
3 -3.12 
4 -3.04 
5 -3.11 
6 -3.22 

proba2.dat 
-3.00 0.080 
-3.05 0.084 
-3.10 0.086 
-3.15 0.097 
-3.20 0.104 
-3.25 0.160 
-3.30 0.230 
-3.35 0.340 
-3.40 0.259 
-3.45 0.123 
-3.50 0.033 
-3.55 0.030 
-3.60 0.012 

Если они совпадают внутри интервала 0,05, то я хочу, чтобы добавить 3-й столбец в proba1.dat со значениями 2-го столбца из proba2.dat, так что я получаю

proba3.dat 
1 -3.56 0.030 
2 -3.40 0.259 
3 -3.12 0.086 
4 -3.04 0.084 
5 -3.11 0.086 
6 -3.22 0.104 

Я попытался с

awk 'FNR == NR { k[$2] = 1; next } { if (k[$1] <= 1+0.025 && k[$1] >= 1-0.025) { print $0 } }' \proba1.dat proba2.dat > proba3.dat 

но печатает только значения, которые соответствуют точно

-3.40 0.259 

, а также там нет первого столбца из proba1.dat. Кто-нибудь есть идея, как это сделать?

+0

Вам нужно совместить * каждую строку с 'proba2.dat' с * каждой * строкой от' proba1.dat'? Для этого вам понадобится цикл. Вы также захотите сохранить всю строку ввода в своем awk-скрипте под значением столбца (надеюсь, они уникальны), чтобы вы могли вернуть их. Возможно, имеет смысл сначала обработать второй файл. –

+0

Да, ты прав. Я пропустил это. – user5694985

ответ

2

Это работает для меня:

awk 'FNR==NR{a[$1]=$2} 
    FNR!=NR{for(i in a){if($2>=i-0.025&&$2<=i+0.025){$3=a[i];print;next}}}' \ 
     proba2.dat proba1.dat 
  • FNR==NR применяется только на первом файле proba2.dat
    • a[$1]=$2 заполняет массив a с первым полем в качестве индекса, а второй в качестве значений.
  • FNR!=NR применяется только на второй файл proba1.dat
    • for(i in a) петля корыто созданного массива Данные о предыдущих a.
    • if($2>=i-0.025&&$2<=i+0.025, если значения в диапазоне от 0,05
    • $3=a[i] установить «новое» третье поле к этому значению, где индекс находится в этом диапазоне.
    • print;next распечатать новую строку и перейти на следующую строку.
+0

Заметьте, вы также можете сказать 'FNR == NR {вещи; next} ', поэтому вам не нужно говорить' FNR! = NR' и просто сказать '{for (i in a) ...}'. – fedorqui

+0

Спасибо. Он работает нормально. – user5694985

0

Давайте напишем небольшую функцию, чтобы округлить число до ближайшего 5:

function myround(val) { 
    n=int(val*100) 
    nearest=sprintf("%.0f", n/5) 
    near5=nearest*5 
    return sprintf("%.2f", near5/100) 
} 

Тогда, это вопрос к петле через 2 файла, хранящего его значения, а затем цикл по первый один ищет ближайшее значение:

awk 'FNR==NR {a[$1]=$2; next} {print $0, a[myround($2)]}' f2 f1 

Все вместе:

awk 'function myround(val) { 
     n=int(val*100) 
     nearest=sprintf("%.0f", n/5) 
     near5=nearest*5 
     return sprintf("%.2f", near5/100) 
} 
FNR==NR {a[$1]=$2; next} {print $0, a[myround($2)]}' f2 f1 

возвращает:

1 -3.56 0.030 
2 -3.40 0.259 
3 -3.12 0.086 
4 -3.04 0.084 
5 -3.11 0.086 
6 -3.22 0.104 
0
awk 'NR==FNR{a[$1]=$2;next}{b=$2;sub(".$",/[0-4]$/?"0":"5");print $1,b,a[$2]}' proba2.dat proba1.dat 
1 -3.56 0.030 
2 -3.40 0.259 
3 -3.12 0.086 
4 -3.04 0.080 
5 -3.11 0.086 
6 -3.22 0.104 
0

чтения файлов в логическом порядке

awk 'FNR==NR{L[++s]=$0;M[s]=$2;next}{for(i=1;i<=s;i++)if(sqrt(($1-M[i])^2)<=0.025)L[i]=L[i] " " $2}END{for(i=1;i<=s;i++)print L[i]}' proba1.dat proba2.dat > proba3.dat 

чтения файлов в обратном порядке

awk 'FNR==NR{V[$1]=$2;next}{for(v in V)if(sqrt(($2-v)^2)<=0.025){print $0 " " V[v];next}print}' proba2.dat proba1.dat > proba3.dat 

В обеих версиях, линия от proba1. который печатается без дополнительной информации rmation if not соответствия найдено в proba2.dat