I am looking at a log file which just tells me the filename and the line number inside that file that has the Error. What I am interested is knowing the encapsulating function. For example, here are the contents of the log file

    Error: foo.file on line wxy
    Error: foo.file on line xyz

and here are the contents of the file foo.file

function abc_1234 (...)


    function def_442 ()
   //Following line number is  WXY
    assign Z ==== X;


    function ghi(...)

  //Following line number is  XYZ
    assign X = X;


Based on the above log file, I want to get function names def_442 and ghi returned. I have tried the following

# look for function definitions and record the function name
# in the func_name variable
/function [[:alpha:]][[:alnum:]]*[[:blank:]]*([^)]*)/ {
  func_name = substr($2, 1, index($2, "(")-1);

# when we reach the target line number, print out the current
# value of func_name
NR == target {
  print func_name

but It is failing on abc_1234 (...) and def_442 (...) as there is a space before (


1 Answer 1


Short of parsing the source code properly, so that we're not thrown off by comments or strings that might falsely match, the below script simply searches backwards from the given line numbers in the given files for the string "function " (in quotes so that you can see the invisible trailing space):

while read -r error file on line linenum
  : "SC2034: $error, $on, and $line are unused"
  printf 'For error in %s on line %d:\n' "$file" "$linenum"
  ed -s "$file" << EOF | sed '1d; s/function //; s/(.*//'
done < logfile

The outer while loop reads the logfile into two important variables: "$file" and "$linenum". It then invokes ed on "$file" and gives it a here-document with a list of instructions, namely:

  1. go to line "$linenum"
  2. search backwards for the string "function " -- there's that invisible space
  3. quit

The output of ed will be two lines: the contents of $linenum, followed by the line before it that matches "function ". That's why we pass all of that output through sed, which is given three commands:

  • 1d -- delete the first line of the output
  • s/function // -- delete the string "function "
  • s/(.*// -- delete from the opening parenthesis onwards

Sample output, given your input, is:

For error in foo.file on line 13:

For error in foo.file on line 25:

Reformat to taste.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.