ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

How extract from path file name

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • How extract from path file name

    Hi
    suppose have in a string a full file path ; example "/home/myflr/myname/myfile.xls". if i would estract the string "myfile", how could do that ?
    thanks in advance

  • #2
    I'd use %ScanR to locate the period and note the position. Then use that as as the starting point for a second %ScanR looking for the slash. Then use the two positions to %Substr the file name.

    Given that the two search arguments are different you could do it in one line. But folks maintaining the app in the future might not thank you.

    Comment


    • #3
      %ScanR was new in i7.3. If you are on i7.2 or lower, you will have to code a loop of some kind and iterate over the characters in the string.

      I haven't run this so there might be a bug, but something like this should do:
      Code:
      Dcl-S pathString  char(256);
      Dcl-S fileName  char(256);
      Dcl-S slash int(5) inz(0);
      Dcl-S period int(5) inz(0);
      Dcl-S i int(5);
      
      // Iterate over all characters in path, backwards, from last non-blank
      // Stop when we have found the last period and the last slash, or if we have finished the string
      i = %len(%trimr(pathString));  // Start at end of string
      DoW (slash = 0 or period = 0) and i > 0;
        If %Subst(pathString:i:1) = '.' and period = 0;  // Find period
          period = i;
        ElseIf %Subst(pathString:i:1) = '/' and slash = 0;  // Find slash
          slash = i;
        EndIf;
        i -= 1;  // Previous character
      EndDo;
      
      If period > 0;
        fileName = %subst(pathString:slash+1:period-(slash+1));  // A Period was found, extract from last slash (or start if no slash found) to period
      Else;
        fileName = %trimr(%subst(pathString:slash+1));  // A Period was not found, so no extension, so from last slash for the whole rest of the string (right trimmed)
      EndIf;

      Comment


      • #4
        Thanks for that Vectorspace - I was convinced that %ScanR was PTF'd into 7.2 but on checking I see it was one of the exceptions.

        Comment


        • #5
          I'm one of those wierdos that modularize the code.

          I suggest creating a procedure called ScanR - as follows:

          Code:
                 // --------------------------------------------------
                 // Procedure name: SCANR
                 // Purpose:        Scan from right to left
                 // Returns:        Position of search string - or 0 if not found.
                 // Parameter:      srch => Search argument
                 // Parameter:      Str => String to be searched
                 // Parameter:      Start => right most position to start
                 // --------------------------------------------------
                 DCL-PROC SCANR ;
                   DCL-PI ScanR INT(10);
                     srch VARCHAR(32000) VALUE;
                     Str VARCHAR(32000) VALUE;
                     Index INT(5) OPTIONS(*NOPASS) VALUE;
                   END-PI ScanR;
          
                   Dcl-S Pos Int(10);
                   Dcl-S Last Int(10);
                   DCL-S lpos INT(10);
                   Dcl-S StrLen Int(10);
          
                   Last = 0;
                   Str = %TrimR(Str);
                   StrLen = %Len(Str);
                   Srch = %TrimR(Srch);
                   If %PARMS = 3;
                     lpos = Index;
                   Else;
                     lpos = %Len(Str);
                   EndIf;
                   DOU Pos = 0 or Pos >Lpos;
                     Last = Pos;
                     If Pos < StrLen;
                       Pos = %Scan(Srch : Str : Pos + 1);
                     Else;
                       Pos = 0;
                     EndIf;
                   EndDo;
          
                   return last ;
                 END-PROC ScanR;
          This stakes 2-3 parms. First one is the search argument, second the string to search and the 'starting' point you can specify if you want.

          The main code can then look like:

          Code:
          Dcl-S pathString  char(256) Inz('/home/myflr/myname/myfile.xls');
          Dcl-S fileName  char(256);
          Dcl-S slash int(5) inz(0);
          Dcl-S period int(5) inz(0);
          Dcl-S i int(5);
          Dcl-S Lgth Int(5);
          
          period = Scanr('.' : PathString); // Find the .
          if period = 0;
            period = %Len(%TrimR(pathString)); // if period isn't found, just give it the length of the string
          EndIf;
          
          slash = Scanr('/' : PathString); // Return the last /
          
          lgth = period - slash - 1; // Determine the length of the name portion of the path
          FileName = %Subst(PathString : slash + 1 : lgth);
          To me the code is more straightforward and it's re-usable. And down the road when you get to 7.3 you can replace the ScanR with %ScanR and remove the procedure...

          Comment


          • #6
            Without %ScanR(), I'd use a regular expression. I personally find it faster and less error prone to write. It is however slightly slower than in-line DIY code (about 0.014 seconds). Splitting the DIY code off into a procedure would likely close that gap a little.

            You won't win friends among dinosaur RPG devs with this however.

            Code:
                  EXEC SQL  
                    set :name = regexp_substr('/home/myflr/myname/MyFile.xls', '(?<=/)[a-z]+(?=\.\D+)',1,1,'i');

            Comment


            • jtaylor___
              jtaylor___ commented
              Editing a comment
              OK, "dinosaurs" was a little harsh. Developers working solely or primarily in RPG are probably unfamiliar with regular expressions.

            • Vectorspace
              Vectorspace commented
              Editing a comment
              If I understand your regex right, it will only work if the filename contains letters only - not numbers or any other valid-for-filename characters. E.g, MyFile001 (number) or MyFile_A (underscore).
              It will also not work if the filename + extension is something like 'MyFile001.abc.txt" - which can happen, and in this example .txt is the extension so MyFile001.abc is the file name without extension.
              Also, you haven't escaped the forward slash in the lookbehind.

            • jtaylor___
              jtaylor___ commented
              Editing a comment
              True that it won't handle numbers or multiple extensions. That versatility would require a more complicated statement. You don't have to escape forward slashes.

          • #7
            Regular expressions are powerful - but look convoluted to the non-Unix, non-C people....

            You'd have to document exactly what you'e doing with that expression...

            Comment


            • #8
              Oh, don't worry, Rocky... they look convoluted to everyone, including Unix/C people ;-)

              Comment


              • #9
                Yeah - I'm old school... keep it KISS (for me that's Keep It Simple Stupid - for others it's Keep It Short and Simple).

                Comment


                • #10
                  Or - Keep It Sweet & Simple...

                  Comment

                  Working...
                  X