foo.txt
:
1 10 11
2 20 22
3 30 32
4 40 42
5 50 52
6 60 62
7 70 72
8 80 82
9 90 92
10 100 110
期待するOut.txt
:
1 10 11
2 20 22
3 30 32
4 40 42
5 50 52
6 60 62
7 70 72
8 80 82
9 90 92
10 100 110
25 250 275 #Line 11
30 300 330 #Line 12
45 550 595 #Line 13
11行は1行から始まり1、2、3列の交互行の合計であり、12行は2行の合計で始まる1、2、3列の交互行の合計です。 13行は11行と12行の列を合わせたものです。 KSHとSolaris 5.10を使用していますが、入力ファイルの値が連続しない場合もあり、3桁の整数を超えない場合もあります。私の入力ファイルには10行しかありません。この目標を達成する方法は?
答え1
$ awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt
1 10 11
2 20 22
3 30 32
4 40 42
5 50 52
6 60 62
7 70 72
8 80 82
9 90 92
10 100 110
25 250 259
30 300 318
55 550 577
上記はGNU awkとLinuxでテストされました。
どのように動作しますか?
-v OFS='\t'
オプション:出力をタブ区切りに設定します。
{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;}; $1=$1; print}
これは各列を繰り返してその値を配列に追加します
s
。各列にi
偶数行が追加され、s[2,i]
奇数行が追加されますs[1,i]
。すべての行の列i
がに追加されますs[3,i]
。その後、ラインを印刷します。
END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}
ファイルの終わりに達すると、結果が印刷されます。まず、奇数行を印刷し()、
n=1
偶数行を印刷してから(n=2
)、最後に合計を印刷します(n=3
)。
サン/ソラリス
Sun/Solaris のデフォルト awk に問題があるという報告を何度も受けました。試してみてください:
nawk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt
または:
/usr/xpg4/bin/awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt
または:
/usr/xpg6/bin/awk -v OFS='\t' '{for (i=1;i<=NF;i++) {s[2-NR%2,i]+=$i;s[3,i]+=$i;};$1=$1;print} END{for (n=1;n<=3;n++) print s[n,1],s[n,2],s[n,3]}' foo.txt
答え2
awk
代わりにこれを使用したいと思いますsed
。これはawk
これを行うスクリプトです。
awk '
(NR%2) == 1 {
odd_col_1 += $1;
odd_col_2 += $2;
odd_col_3 += $3;
print $0;
}
(NR%2) == 0 {
even_col_1 += $1;
even_col_2 += $2;
even_col_3 += $3;
print $0;
}
END {
print odd_col_1, odd_col_2, odd_col_3;
print even_col_1, even_col_2, even_col_3;
print odd_col_1+even_col_1, odd_col_2+even_col_2, odd_col_3 + even_col_3;
}
' foo.txt
これは、「NR」レコード番号の組み込み変数、awk
テキストファイルをフィールドで区切る方法、および「END」構造を利用します。
答え3
まあ、私はこの問題に対する非常に基本的な解決策を自分で見つけました。しかし、誰かがより良い答えを持っていることを願っています。
#remove even lines
sed -i '0~2d' foo.txt > oddlines
#oddlines sum
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' oddlines > oddlines_sum
#remove even lines
sed -i '1~2d' foo.txt > evenlines
#evenlines sum
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' evenlines > evenlines_sum
#combine
cat evenlines_sum >> oddlines_sum
#for total sum of foo.txt
awk '{a=a+$1}{b=b+$2}{c=c+$3}END{print a,b,c}' foo.txt > foo_sum
#final output
cat oddlines_sum >> foo.txt
cat foo_sum >> foo.txt`
私は私の解決策が非常に基本的であることを知っています。しかし、私は最善を尽くしました。
答え4
sed ' 1x;1s/^/654321/;1x;N;y/ /\n/;G;:t
s/\([0-9]*\)\n*\n\(.*\)\(.\)/l\3\1+s\3 \2/;tt
p;$!d;g;s/./l&/g;s/$/fcl3l6+l2l5+l1l4+f/' file |
dc 2>/dev/null |sed '11,$N;/\n/N;s/[^0-9] */\t/g' file -
これはあなたに役立ちます。内部ストリームを使用してdc
電卓/コンパイラのいくつかのマクロ前処理を処理することによって機能します。sed
基本的にsed
言うdc
(bc
コンパイラ - Solarisシステムに存在する必要があります)6つの値を追跡し、1行の入力行すべてをロードし、各列の値を増やした後に結果を再保存します。最後の入力行にもう一度呼び出すようにsed
指示し、6つの値をすべてstdoutに出力します。dc
13行の合計を取得するには、保存された合計を再度呼び出して加算するだけです。
l3l6+...f
最初の行で任意の配列から値をロードしようとすると、配列が空で警告が発生するため、dc
stderrをダンプします。残りの時間は空ではなく、必要に応じて保存/復元するため、これは意味がありません。/dev/null
l
[123456]
最後に、もう一つはsed
すべてを一つにまとめます。dc
出力を尾部に追加します。file
すべてのスペースを1行に1つのタブに置き換えます。(\t
ここではエスケープ文字を使用していますが、実際のスクリプトではリテラル<tab>文字でなければなりません)。
出力
1 10 11
2 20 22
3 30 32
4 40 42
5 50 52
6 60 62
7 70 72
8 80 82
9 90 92
10 100 110
25 250 259
30 300 318
55 550 577