'awk print sum of group of lines
I have a file with a column named (effect) which has rows separated by blank lines,
(effect)
1
1
1
(effect)
1
1
1
1
(effect)
1
1
I know how to print the sum of column like
awk '{sum+=$1;} END{print sum;}' file.txt
Using awk how can I print the sum of each (effect) in for loop? such that I have three lines or multiple lines in other cases like below
sum=3
sum=4
sum=2
Solution 1:[1]
With your shown samples, please try following awk code. Written and tested in GNU awk.
awk -v RS='(^|\n)?\\(effect\\)[^(]*' '
RT{
gsub(/\(effect\)\n|\n+[[:space:]]*$/,"",RT)
num=split(RT,arr,ORS)
print "sum="num
}
' Input_file
Explanation: Simple explanation would be, using GNU awk. In awk program set RS as (^|\n)?\\(effect\\)[^(]* regex for whole Input_file. In main program checking condition if RT is NOT NULL then using gsub(Global substitution) function to substitute (effect)\n and \n+[[:space:]]*$(new lines followed by spaces at end of value) with NULL in RT. Then splitting value of RT into array named arr with delimiter of ORS and saving its(total contents value OR array length value) into variable named num, then printing sum= along with value of num here to get required results.
With shown samples, output will be as follows:
sum=3
sum=4
sum=2
Solution 2:[2]
This should work in any version of awk:
awk '{sum += $1} $0=="(effect)" && NR>1 {print "sum=" sum; sum=0}
END{print "sum=" sum}' file
sum=3
sum=4
sum=2
Solution 3:[3]
Similar to @Ravinder's answer, but does not depend on the name of the header:
awk -v RS='' -v FS='\n' '{
sum = 0
for (i=2; i<=NF; i++) sum += $i
printf "sum=%d\n", sum
}' file
RS='' means that sequences of 2 or more newlines separate records.
The Field Separator is newline.
The for loop omits field #1, the header.
However that means that empty lines truly need to be empty: no spaces or tabs allowed. If your data might have blank lines that contain whitespace, you can set
-v RS='\n[[:space:]]*\n'
Solution 4:[4]
$ awk -v RS='(effect)' 'NR>1{sum=0; for(i=1;i<=NF;i++) sum+=$i; print "sum="sum}' file
sum=3
sum=4
sum=2
Solution 5:[5]
I'd use a readstream to read chuncks then check character by character until you have an object, defines as the number of { === }. Something like this:
const fs = require("fs");
async function read() {
//TODO: add check for fileexists
const obj = await findFirstJsonObjectFromFile("file.json");
//TODO: convert to json object and return
console.log(obj);
}
const findFirstJsonObjectFromFile = async fileName => {
return new Promise(resolve => {
const fileStream = fs.createReadStream(fileName, { highWaterMark: 60 });
const jsonString = [];
let started = 0;
fileStream
.on("error", () => resolve(jsonString.join("")))
.on("end", () => resolve(jsonString.join("")))
.on("data", chunk => {
for (let i = 0; i < chunk.length; i++) {
const a = String.fromCharCode(chunk[i]);
jsonString.push(a);
if (a === "{") {
started++;
} else if (a === "}" && started === 1) {
resolve(jsonString.join(""));
} else if (a === "}") {
started--;
}
}
});
});
};
//TODO: loop over all files and send as parameter
read();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | RavinderSingh13 |
| Solution 2 | |
| Solution 3 | glenn jackman |
| Solution 4 | karakfa |
| Solution 5 |
