0

In a function, I'm trying to extract the process ID from a line of text. Also, I'm trying to return that process ID:

#!/bin/bash

regex="[a-z]* ([0-9]+)  .*"
indexRawRow="sahandz 9040  other stuff comes here"
getPidFromRow() {

        if [[ $1 =~ $regex ]]
        then
                pid=${BASH_REMATCH[1]}
        else
                pid=""
        fi

        echo "pid is $pid inside function"

        return $pid
}

processId=$(getPidFromRow "$indexRawRow")

echo "pid is $processId outside of function"

The output is:

pid is pid is 9040 inside function outside of function

There are a few problems here:

  1. The two echo statements seem interwoven, indicating that the function and the main scope are running in paralell. Is this supposed to happen? Can it be turned off?
  2. The outside scope never gets the value of the process ID. As you can see, it's only printed once. Through testing, I know that it is only the echo inside of the function that is printing the process ID 9040. The outside scope seems to not have gotten the process ID.

What is the reason for these problems?

Sahand
  • 7,980
  • 23
  • 69
  • 137
  • Where is `outside of function` coming from? – Barmar May 09 '19 at 17:02
  • 1
    What's producing the text `outside of function`? Nothing is running in parallel here. `$(...)` waits for the function to complete, then uses its standard output as the value to assign to `processID`. If you want the exit status, check the value of `$?` after the function exits. – chepner May 09 '19 at 17:02
  • 1
    Generally speaking, you don't use `return` like you would in another language. It can only be used to produce an exit status between 0 and 255, not an arbitrary value. – chepner May 09 '19 at 17:03
  • If you want to write something as informational logging, that belongs on *stderr*, not stdout. Everything you write to stdout is *output*, and is thus captured in a command substitution and (in present case) assigned to the variable `processId`. – Charles Duffy May 09 '19 at 17:04
  • @Barmar: Sorry, there was an editing mistake on my behalf. I have corrected the bash script so that it generates the same output as I have specified – Sahand May 09 '19 at 17:07
  • @Sahand, ...the reason for that output is described above (re: all things written to stdout being *output*, thus captured by command substitution syntax), and likewise in the flagged duplicate. – Charles Duffy May 09 '19 at 17:07

1 Answers1

2

Your assumptions are convoluted here, what you are seeing in the variable processId at the output of $(..) is the output of the echo statement and not the return-ed value from function.

You simply can't return strings from a function in bash. Just unsigned integer codes from 0-255. If you were to return only the the matched group from the function, leave out the return statement and just print the matched group

getPidFromRow() {
    # Your other code here
    # ..
    printf '%d\n' "$pid"
}
Inian
  • 80,270
  • 14
  • 142
  • 161
  • 2
    Probably good form to have a trailing newline and thus to have output be a valid UNIX line of text (which will then be properly stripped by the command substitution, but that way other idioms like `read value < <(getPidFromRow)` work). – Charles Duffy May 09 '19 at 17:06
  • I'd also recommend returning nonzero (error) status if the match failed. – Gordon Davisson May 09 '19 at 20:48