Передача нескольких файлов в качестве аргументов в Bash Scripting и сохранение их содержимого в двух массивах - PullRequest
1 голос
/ 22 октября 2019

Я пытался написать скрипт, который может получить несколько файлов в качестве входных данных. Каждая строка файла имеет такую ​​форму «num1: num2», и я хочу сохранить num1 и num2 в двух разных массивах, а затем вычислить суммы.

#!/bin/bash

args=("$@")
declare -a X
declare -a Y
for ((i=0; i<=${#args}; i++)) do
  input="${args[$i]}"

let  j=0
while  IFS=: read x y
  do
   X+=("$x")
   Y+=("$y")
   let j=j+1
 done < "$input"
  sumx=0
  sumx2=0
  sumy=0
  a=0
  sumxy=0
  b=0
  err=0
  for ((k=0; k<j; k++)) do
    sumx=  $(echo "scale=3; sumx + X[$k]" | bc -l)
    sumx2= $(echo "scale=3;sumx2 + X[$k]^2" | bc -l)
    sumy=  $(echo "scale=3;sumy + Y[$k]" | bc -l)
    sumxy=  $(echo "scale=3;sumxy + X[$k]*Y[$k]" | bc -l)
  done
  echo "$sumx"
done

Ответы [ 2 ]

2 голосов
/ 22 октября 2019

awk на помощь!

, так как вы не опубликовали ни одного примера ввода, давайте создадим

$ seq 10 | paste -d: - - | tee file1 file2

$ head file{1,2}
==> file1 <==
1:2
3:4
5:6
7:8
9:10

==> file2 <==
1:2
3:4
5:6
7:8
9:10

Легко добавить соответствующие поля с помощью awk.

$ awk -F: '{sum1+=$1; sum2+=$2} END{print sum1,sum2}' file{1,2}

50 60

или добавьте другие вычисления

$ awk -F: '{sum1+=$1; sum2+=$2; sumsq1+=$1^2; sum12+=$1*$2} 
       END {print sum1,sum2,sumsq1,sum12}' file{1,2}

50 60 330 380
1 голос
/ 23 октября 2019

@ karakfa уже показал лучший способ сделать это в awk;Я хотел бы попытаться исправить версию Bash. Основная проблема - некоторые основные синтаксические ошибки:

Во-первых, в цикле:

for ((i=0; i<=${#args}; i++)) do

${#args} не получает количество элементов в массиве, оно получает длину (в символах) первого элемента массива. Вы хотите ${#args[@]} вместо этого. Или, что еще лучше, вообще не перебирайте индексы массива, просто перебирайте элементы массива напрямую:

for input in "${args[@]}"; do

Второй и третий, в строках расчета, например

sumx=  $(echo "scale=3; sumx + X[$k]" | bc -l)

... нельзя ставить пробелы после знака = (они полностью меняют значение команды ), а также ссылки на переменные требуют $${} для массиваэлемент), чтобы сказать оболочке заменить их:

sumx=$(echo "scale=3; $sumx + ${X[$k]}" | bc -l)

Это то, что вызывало сообщения об ошибках, которые вы получили. bc не имеет представления о переменных оболочки;он будет обрабатывать sumx как неинициализированную переменную bc, но X[1] является недопустимым синтаксисом bc (обратите внимание, что $k будет заменен).

Если бы вы действительно делали это в оболочке (а не awk), я бы также предложил упростить ее, удалив массивы. Нет смысла читать содержимое файлов в массив, а затем выполнять итерации по массиву, когда вы можете просто вычислить, как вы читаете:

while IFS=: read x y; do
    sumx=$(echo "scale=3; $sumx + $x" | bc -l)
    sumx2=$(echo "scale=3; $sumx2 + $x^2" | bc -l)
    sumy=$(echo "scale=3; $sumy + $y" | bc -l)
    sumxy=$(echo "scale=3; $sumxy + $x*$y" | bc -l)
done < "$input"
...