[Solved] Read last line from Process

Post your Gambas programming questions here.
Post Reply
User avatar
Philippe734
Posts: 20
Joined: Sunday 16th February 2020 7:37pm
Contact:

[Solved] Read last line from Process

Post by Philippe734 »

Hello,
Considering the following concept bash:

Code: Select all

command | while read line; do
    if [ "$condition" == "$line"  ]; then
        echo "$line"
        break
    fi
    done
With an example:

Code: Select all

x=10
(while :; do echo "$x";   x=$(( $x + 1 )); done) | while read line; do
    if [ "256071" == "$line"  ]; then
        echo "$line"
        break
    fi
    done
I want to convert this in Gambas, with Exec and Process Read, please, can you help me ?
hProc = Exec ["command"] For Read As "Contents"
Public Sub Contents_Read()  
  Dim sLine As String
  
  Repeat
    ' How to read the last line of the standard process output ?
   ...
    'sOutput &= sLine
  Until sOutput = "text"
  ' To kill or close the process : Contents_Kill or hProc.Kill or hProc.Close ?
  
End
In Contents-Read () how to read the last line of the standard output of the process ?
What code use to close or kill the process ?
Last edited by Philippe734 on Tuesday 31st March 2020 9:35am, edited 4 times in total.
Linux & Android enthusiast - France
User avatar
cogier
Site Admin
Posts: 1118
Joined: Wednesday 21st September 2016 2:22pm
Location: Guernsey, Channel Islands

Re: Read last line from Process

Post by cogier »

Run this code in a new 'Graphical' application. Hopefully it will help you.
hProcess As Process
TextArea1 As TextArea

Public Sub Form_Open()

  BuildForm
  Go

End

Public Sub Go()

  hProcess = Shell "tree" For Read As "Process"

End

Public Sub Process_Read()

  Dim sLine As String

  Read #Last, sLine, -256
  TextArea1.Text &= sLine

End

Public Sub BuildForm()

  With Me
    .Arrangement = Arrange.Vertical
    .Height = 500
    .Width = 300
    .Padding = 5
  End With

  With TextArea1 = New TextArea(Me) As "TextArea1"
    .Expand = True
  End With

End
User avatar
Philippe734
Posts: 20
Joined: Sunday 16th February 2020 7:37pm
Contact:

Re: Read last line from Process

Post by Philippe734 »

I known already it, I know read the help of Gambas ;)
Read #Last, sLine, -256
It's not the answer I need. Currently, this line return the whole output. Considering a bash command which run in an infinite loop. I want only the last line of the standard output, test it with my condition and let the run until my condition is true, then kill the process.
Edit : for more detail my need, I edit my first post with a concrete bash command.
Linux & Android enthusiast - France
User avatar
Serban
Posts: 39
Joined: Saturday 28th March 2020 8:17am
Location: Alexandria
Contact:

Re: Read last line from Process

Post by Serban »

Maybe I got it wrong...
In my view, what you need is to perform a dynamycal analyisis on the output of the console.
That is more difficult, since you need to know precisely if the output is something formatted as lines. Otherwise, you end up with an endless string which has only one line, which is always "the last line". So we're in a vicious cricle here: what is "last line"?
If I understood it right, the first step would to direct the output from the console, into a string variable.
As an intermediate phase, you load it into a TextArea and get the image on how it looks like:
All you need here is a FMain module and a TextArea1 control.
To trigger the process, put a Button1 above the TextArea1, then on Button1_Click() event, call the procedure that does the Shell or Exec. Say...

'---
Public Sub GetConsoleOutput()
'--- Code for spying the console.
End
'---
Public Sub Button1_Click()
  GetConsoleOutput()
End
'--- This goes into FMain.Class:
Dim strConsoleOutput, strToken, strCurrentLine As String
'...
TextArea1.Wrap=False
TextArea1.Text=strConsoleOutput
'--- Now, how does it look like? Do we have lines?
'--- IF so, then we cycle through the lines, using a Stream, then a clause.
'... stream Dim ,open etc.
While Not hndStream.EOF
  If InStr(strToken ,strCurrentLine) Then   '--- We found what we're looking for. Do the job we need.
    DoTheJobINeed()
  Else    '--- We might need to do something here. Either ignore the line since we are missing what we are looking for, OR whatever else.
    DoTheAlternateJob()
  End If
Wend

If you do this, you need to set the Wrap property to "False ", to prevent wrapping the contents. This is how you find out if there is only one string, or there are more lines.
In the code above, I admitted by default that we got LINES. That is, more than one line, which is always "LastLine".
NOTE:
I wrote the code in place from memory so YOU GOT TO TEST IT, and obviously, fill the required lines to catch the console output into the string [strConsoleOutput].
Since I hate console, I leave it up to you to write the appropriate code.
...
The other way around...
I have to figure out how to do this, because it goes beyond my understanding how you can test a string that is continuously generated and you want to find something in it, in real time. Meaning, as it is generated.
---
The other thing you need to do, is write the code for the Stream: to open it, read the lines from [strConsoleOutput] into [strCurrentLine] and test the [strToken]
As I said though, maybe I got it wrong...
The only thing necessary for the triumph of evil is for good men to do nothing.”― Edmund Burke;
It's easy to die for an idea. It is way harder to LIVE for your idea! (Me)
User avatar
Philippe734
Posts: 20
Joined: Sunday 16th February 2020 7:37pm
Contact:

Re: Read last line from Process

Post by Philippe734 »

Solved:
I was not on the right the way. In Process_Read() we need to use Line Input instead of Read for that context.
hProc = Exec ["command"] For Read As "Contents"
Public Sub Contents_Read()  
  Dim sLine As String
  
  Repeat
    Line Input #hProc, sLine    
  Until sLine = "textcondition"
  sOutput = sLine
  
  hProc.Kill
  hProc.Close
End
Linux & Android enthusiast - France
User avatar
Serban
Posts: 39
Joined: Saturday 28th March 2020 8:17am
Location: Alexandria
Contact:

Re: Read last line from Process

Post by Serban »

Philippe734 wrote: Tuesday 31st March 2020 9:35am we need to use Line Input instead of Read for that context.
That is the point:
In the code I put there, and I mentioned "I SUPPOSED", the idea was to "Read Line", but the specifics of the output, were only a supposition.
Without a line formatted output, it's very difficult to "catch" a certain token, since the "one line" output is constantly changing.
If we have lines, it's easier, we can kill the process, once the token showed up. That spears CPU/RAM time.
The other approach, would require a loop (While/Wend) and reading recursively the current output, as it was generated at each iteration.
While the test condition is static, the test string changes continuously.
Problem is that I know nothing about how can you get out of the Shell/Exec the value of strOutput BEFORE the command ends. The test is otherwise, trivial.
If InStr(strToken, strOutput) Then
... do whatever necessary
The only thing necessary for the triumph of evil is for good men to do nothing.”― Edmund Burke;
It's easy to die for an idea. It is way harder to LIVE for your idea! (Me)
Post Reply