web-dev-qa-db-ja.com

Bashで2つのテキストファイルから数値を追加するにはどうすればよいですか?

次のような数値を含むtxtファイルがあります。

1  
2  
3  
4  
5  

そして、私は同じ数の行を含むが他の数を含む別のtxtファイルを持っています:

6  
7   
8  
9  
10

1 + 6、2 + 7、3 + 8などを一緒に追加したいのですが、スクリプトはどのように記述すればよいですか?

ちなみに、これまでにさまざまな回答がありましたが、ファイルで試してみないと、10進数を処理できないメソッドがあることがわかりました。一部のファイルには小数が含まれていますが、正確である必要があるため、回答を追加したい場合は、小数を正確に計算できる方法を示すことができます。ありがとう。

6
OhLook

これは、多くのツールで解決できる基本的なタスクです。 paste + awkコンボは非常に便利です:

$ paste file1 file2 | awk '{$0=$1+$2}1'
7
9
11
13
15
9
jimmij

paste行に沿って、ただしbcで計算を行う:

$ paste -d+ file1 file2 | bc
7
9
11
13
15

中間結果(bcの前):

$ paste -d+ file1 file2
1+6
2+7
3+8
4+9
5+10

よりbash中心のソリューションの場合、file2には少なくともfile1と同じ数の行があると仮定します。

mapfile -t file1 < file1
mapfile -t file2 < file2
for((i=0; i < ${#file1[@]}; i++))
do
  printf '%d\n' $((file1[i] + file2[i]))
done

...そして整数以外の場合は、アイデアを組み合わせます:

mapfile -t file1 < file1
mapfile -t file2 < file2
for((i=0; i < ${#file1[@]}; i++))
do
  printf '%d + %d\n' "${file1[0]}" "${file2[0]}" | bc
done
13
Jeff Schaller

awkのみのソリューション

awk '(getline a <"file2") <= 0 {exit}; {print $0 + a}' file1
6
iruvar

これはbashのみのソリューションです(他の実行可能ファイルは使用されません):

while read X; do read Y <&3; echo $((X + Y)); done <file1 3<file2

この場合、file1は標準入力にリダイレクトされ、file2は任意のファイル記述子3にリダイレクトされます。

次に、whileはfile1からXに行を読み取り、反復ごとにファイル記述子3(file2)から行を明示的に読み取り、シェル演算を使用して計算を実行します。

1
Jason Musgrove

過度に複雑Bashのみソリューション

ファイル/ tmp/file1

1
2
3
4
5

および/ tmp/file2

6
7
8
9
10

次のように記述しますscript.sh

#!/bin/bash
# counters
n=0
m=0
i=0

# read every line from the first file
while read line1;
do
  declare firstfile[$n]=$line1
  n=$((n+1))
done <$1

# read every line from the second file 
while read line2;
do
  declare secondfile[$m]=$line2
  m=$((m+1))
done <$2

# combine them with arithemtic
while read foo;
do
  num=$((${firstfile[$i]} + ${secondfile[$i]}))
  echo $num 
  i=$((i+1))
done <$1

そしてそれを実行する

#:~$ bash script.sh /tmp/file1 /tmp/file2
7
9
11
13
15
0
Robert Riedl

OK、それは少し不可解ですが、bash演算、pasteおよびsedも使用します。

$ # debug
$ paste -d+ <(sed 's/\(.*\)/echo $((\1/' file1) <(sed 's/\(.*\)/\1))/' file2)
echo $((1+6))
echo $((2+7))
echo $((3+8))
echo $((4+9))
echo $((5+10))

$ eval "$(paste -d+ <(sed 's/\(.*\)/echo $((\1/' file1) <(sed 's/\(.*\)/\1))/' file2))"
7
9
11
13
15
0
Freddy