'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