2016-04-09 2 views
1

Как я могу изменить файл, который выглядит так:Баш строки сценария в Колонном

A 25 
B 26 
A 14 
D 39 
E 42 

A 74 
B 36 
A 81 
D 96 
E 17 

A 23 
B 14 
A 74 
D 87 
E 17 

в файл с рядами как колонны, но только один раз, и их по ценности в колонках? Примерно так:

A B  A D E 
25 26 14 39 42 
74 36 81 96 17 
23 14 74 87 17 

Мои столбцы повторяются каждые 29 строк, а некоторые столбцы, такие как A, имеют одинаковое имя.

+0

Вы предприняли какие-либо попытки? – anubhava

+0

Последние два дня - это единственное, что я делаю :) – jimakos17

+3

Не говорите * нам, что вы сделали попытку; * шоу * мы попытка. – chepner

ответ

5

Вы можете использовать следующую awk скрипт для преобразования файла:

transform.awk:

{ 
    # On the first record this loop runs twice. once 
    # for the headers once for the first line of data. 
    # In all subsequent lines is prints only the data 
    # because h==1. 
    for(;h<=1;h++){ 
     for(i=1+h;i<=NF;i+=2){ 
      printf "%s ", $i 
     } 
     printf "\n" 
    } 
    h=1 
} 

Затем выполнить это следующим образом:

awk -f transform.awk RS='' file 

Выход:

A B A D E 
25 26 14 39 42 
74 36 81 96 17 
23 14 74 87 17 

Чтобы получить надлежащее соответствие столбцов можно просто труба, column -t:

awk -f transform.awk RS='' file | column -t 

Выход:

A B A D E 
25 26 14 39 42 
74 36 81 96 17 
23 14 74 87 17 

Ключевым моментом здесь является использование переменной RS (разделитель записей). Использование пустой строки для RS отделяет записи пустыми строками. Это то же самое, что и установка \n\n+ (одна или несколько пустых строк). Первая запись примеров будет выглядеть следующим образом:

A 25 
B 26 
A 14 
D 39 
E 42 

awk по умолчанию расщепляется на [[:space:]]+ который включает в себя новые строки. Это дает нам следующие поля для записи.

A 25 B 26 A 14 D 39 E 42 

Алгоритм, показанный выше, преобразует эти поля в желаемый результат.

+0

Спасибо, hek2mgl за ваш ответ, но я получаю: column: Недопустимый или неполный многобайтовый или широкий символ. – jimakos17

+1

@EdMorton Вы правы, ввод как '\ n \ n \ n +' работает также с 'RS = '''! – hek2mgl

+0

@ jimakos17 Используете ли вы язык юникода? – hek2mgl

2

альтернатива awk раствора с другой Unix набор инструментов (широко используется)

$ sed '/^$/d' file | 
    pr -3ts' '   | 
    tr '\t' ' '   | 
    tr -s ' '   | 
    cut -d' ' -f1,2,4,6 | 
    tr ' ' '\n'   | 
    pr -5ts' '   | 
    column -t 



A B A D E 
25 26 14 39 42 
74 36 81 96 17 
23 14 74 87 17 

первое магическое число 3 это число повторных участков (или количество строк без заголовка) и второе магическое число 5 является количество элементов в каждая секция (или количество столбцов)

0

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

Сценарий просто читает колонки-1 и столбец-2 на отдельные индексированные массивы (a1 & a2) до тех пор, пустая строка не встречаются, и, если это первый раз через, печатают строки заголовка (и задает заголовок флаг h, чтобы не печатать снова), а затем печать данных в a2.

Когда конец файла достигнут, он просто печатает окончательную строку данных.

#!/bin/bash 

fname="${1:-/dev/stdin}" 

declare -i h=0 
declare -a a1 
declare -a a2 

while read -r line; do 
    if [ "$line" != "" ]; then 
     a1+=(${line%% *}) 
     a2+=(${line##* }) 
    else 
     [ "$h" -eq 0 ] && { printf " %2s" ${a1[@]}; echo ""; h=1; } 
     printf " %2s" ${a2[@]} 
     echo "" 
     unset a1; unset a2; 
    fi 
done < "$fname" 

printf " %2s" ${a2[@]} 
echo "" 

Использование/выход

$ bash r2c.sh dat/r2c.txt 
    A B A D E 
25 26 14 39 42 
74 36 81 96 17 
23 14 74 87 17 
1

Для удовольствия, некоторые непрозрачные, жемчужно-иш рубин:

ruby -00 -lane ' 
    headers, values = $F.each_with_index.partition {|(v,i)| i.even?} 
    puts headers.collect(&:first).join(" ") if $. == 1 
    puts values.collect(&:first).join(" ") 
' file 
+0

Прохладный! хорошее решение. – JJoao

0

Или Лил немного больше р-экспоненциальная ориентированный:

perl -0pE 'say s/\s*\d+\h*\n|\n.*/ /sgr; s/(^|\n)\w\s*/ /g' file