2013-03-15 3 views
1

Я пытаюсь написать сценарий Bash, который читает файлы с несколькими столбцами данных и умножает каждое значение во втором столбце на каждое значение в третьем столбце, добавляя вместе результаты всех этих умножений ,Использование awk с операциями над переменными

Например, если файл выглядит следующим образом:

Column 1 Column 2 Column 3 Column 4 
genome  1   30   500 
genome  2   27   500 
genome  3   83   500 
... 

Скрипт должен умножить 1 * 30, чтобы дать 30, то 2 * 27, чтобы дать 54 (и добавить, что до 30), то 3 * 83 чтобы дать 249 (и добавить, что до 84) и т. д.

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

Вот что я написал до сих пор:

for file in fileone filetwo 
do 
    set -- $(awk '/genome/ {print $2,$3}' $file.hist) 
    var1=$1 
    var2=$2 
    var3=$((var1*var2)) 
    total=$((total+var3)) 

    echo var1 \= $var1 
    echo var2 \= $var2 
    echo var3 \= $var3 
    echo total \= $total 
done 

Я попытался помещая «во время чтения» петли вокруг все, но не может получить переменные для обновления каждой строки. Я думаю, что я ошибаюсь!

Я очень новичок в написании сценариев Linux и Bash, поэтому любая помощь будет принята с благодарностью!

ответ

2

Это потому, что awk считывает весь файл и запускает свою программу на каждой строке. Таким образом, вывод, который вы получите от awk '/genome/ {print $2,$3}' $file.hist будет выглядеть

1 30 
2 27 
3 83 

и так далее, что означает, в сценарии Баш, команда set выполняет следующие переменные задания:

$1 = 1 
$2 = 30 
$3 = 2 
$4 = 27 
$5 = 3 
$6 = 83 

и т.д. Но вы используете только $1 и $2 в вашем скрипте, что означает, что остальная часть содержимого файла - все после первой строки - отбрасывается.

Честно говоря, если вы не делаете этого просто, чтобы узнать, как использовать bash, я бы сказал, просто сделайте это в awk. Так как awk автоматически запускает каждую строку в файле, будет легко размножать столбцы 2 и 3 и сохранить общее количество.

awk '{ total += $2 * $3 } ENDFILE { print total; total = 0 }' fileone filetwo 

Здесь ENDFILE это специальный адрес, который означает «запустить этот следующий блок в конце каждого файла, а не в каждой строке.»

Если вы в делаете это для образовательных целей, позвольте мне сказать, что это: единственное, что вам нужно знать о выполнении арифметических операций в Баше является то, что вы никогда не должны делать арифметику в Баше :-P серьезно, когда вы хотите для управления числами, bash является одним из наименее хорошо приспособленными инструментами для этой работы. Но если вы действительно хотите знать, я могу отредактировать это, чтобы включить некоторую информацию о том, как вы могли бы выполнить эту задачу в основном в bash.

+0

Спасибо за объяснение! На самом деле это небольшая часть более крупного скрипта bash, поэтому я старался сохранить все вместе просто для простоты. – Joltex

0

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

for f in file1 file2; do 
    total=0 
    while read -r _ x y _; do 
     ((total += x * y)) 
    done < "$f" 
    echo "$total" 
done 
+0

Прохладный! Спасибо. – Joltex

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