Search code examples
arraysbashgrepport-number

Bash - Read portnumbers of certain service(s) into array


I'm searching for port numbers with grep (in a bash script)

portstr=$(lsof -i -P -n | grep LISTEN | grep sshd)

portstr now looks something like this

sshd       673            root    3u  IPv4  14229      0t0  TCP *:22 (LISTEN)
sshd       673            root    4u  IPv6  14231      0t0  TCP *:22 (LISTEN)

now I want to extract the numbers between the colon (:) and the following blank space, to get something like this

portarray[0]=>22
portarray[1]=>22

thank you

I tried this

    var="[a1] [b1] [123] [Text text] [0x0]"
    regex='\[([^]]*)\](.*)'
    while [[ $var =~ $regex ]]; do
      arr+=("${BASH_REMATCH[1]}")
      var=${BASH_REMATCH[2]}
    done

from here. But nothing really worked out.


Solution

  • You might use awk by setting the field separator to either 1 or more spaces or a colon using [[:space:]]+|

    Check if the first field is sshd, the last field is (LISTEN) and then print the second last field:

    portstr=$(lsof -i -P -n | awk -F"[[:space:]]+|:" '$1=="sshd" && $NF == "(LISTEN)" {print $(NF-1)}')
    echo "$portstr"
    

    For the output of lsof -i -P -n being:

    sshd       673            root    3u  IPv4  14229      0t0  TCP *:22 (LISTEN)
    sshd       673            root    4u  IPv6  14231      0t0  TCP *:22 (LISTEN)
    

    The output of the command:

    22
    22
    

    Reading this page you can put the output of the command into an array:

    portarray=( $(lsof -i -P -n | awk -F"[[:space:]]+|:" '$1=="sshd" && $NF == "(LISTEN)" {print $(NF-1)}') )
    
    for port in "${portarray[@]}"
    do
       echo "$port"
    done