2015-08-21 4 views
0

У меня есть папка с 1000 текстовыми файлами с разделителями табуляции. Одна половина моих файлов называется sampleX.features.tab, а другая половина - sampleX.scores.tab.Объединение столбцов из нескольких файлов linux

«sampleX» отличается для каждого файла. Таким образом, существует:

sample1.features.tab 
sample1.scores.tab 
sample2.features.tab 
sample2.scores.tab 
sample3.features.tab 
sample3.scores.tab 

все файлы имеют одинаковое количество строк.

друг от .features.tab Я хочу, чтобы извлечь некоторые столбцы

cut -f1,5,9,10,19,20 

от каждого .scores.tab Я хочу, чтобы извлечь две колонки

, то я хочу, чтобы объединить все эти столбцы в новом файле с именем sampleX.final.tab (так sample1.final.tab, sample2.final.tab, ...)

и вот где я застрял. Как я могу объединить эти вещи в Linux?

+0

как являются '' features' и оценки 'объединены в' final'? строка в 'features' соответствует строке в' score'? – BeyelerStudios

+0

Да, это действительно так. – user1987607

ответ

2

Одним из способов является конвейерный вывод пропила в файлы:

cut -f1,5,9,10,19,20 sample1.features.tab > features1 
cut -f1,7 sample1.scores.tab > scores1 

, а затем вставлять их вместе:

paste features1 scores1 

Doing это для 1000s файлов я бы написать сценарий зацикливание через имена файлов.

Обновление: Выше решение, вероятно, проще всего запомнить (это несколько интуитивно понятно). Однако, если комбинация столбцов из разных файлов требуется на лету (например, при печати с Gnuplot) ответ пользователем liborn работает, а именно

paste <(cut -f... file1) <(cut -f... file 2) 

на стандартный вывод или

paste <(cut -f... file1) <(cut -f... file 2) > newfile 

в NewFile ,

+0

вы били меня по минутам :) – BeyelerStudios

0

Вот awk скрипт, чтобы сделать это (обратите внимание на каждую пару файлов нужно, чтобы поместиться в памяти):

# test.awk 
# 

BEGIN { 
} 

{ 
    ext=substr(FILENAME, length(FILENAME) - 10) 
    if(match(ext, "scores.tab")) { 
    arr[FNR] = (arr[FNR] "  " $1 " " $7) 
    } else { 
    arr[FNR] = (arr[FNR] "  " $1 " " $5 " " $9 " " $10 " " $19 " " $20) 
    } 
} 

END { 
    for (i=1; i<=FNR; i++) { 
    sub(/^  /, "", arr[i]); 
    print arr[i] 
    } 
} 

затем просто цикл по файлам:

# merge.sh 
# 

for i in {1..1000} 
do 

    features="sample$i.features.tab" 
    scores="sample$i.scores.tab" 
    final="sample$i.final.tab" 

    awk -f test.awk $features $scores > $final 
done 
1

Вы ищете process substitution. В Bash вы:

paste \ 
    <(cut -f1,5,9,10,19,20 sample1.features.tab)\ 
    <(cut -f1,7 sample1.scores.tab)\ 
> sample1.out 

Чтобы сделать это на весь свой каталог, вы, вероятно, хотите что-то вроде этого (вы должны установить GNU parallel):

ls *.scores.tab | 
    cut -f1 -d. | 
    parallel "paste <(cut -f1,5,9,10,19,20 {}.features.tab) <(cut -f1,7 {}.scores.tab) > {}.out" 
+0

хотя у этого есть проблемы с пробелами в именах файлов его хорошее решение – BeyelerStudios

+0

Я стремился к низшему подмножеству синтаксиса, который решит проблему OP. «Котировки опущены для краткости». ;) – liborm

Смежные вопросы