A Stanza File Parser in Pure ksh


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting A Stanza File Parser in Pure ksh
# 1  
Old 01-03-2019
A Stanza File Parser in Pure ksh

As it was ultimately Don Craguns idea that saved the whole project i can as well give something back to the community. This is my stanza file parser, which was written only using ksh without any external programs.

The stanza structure
There is some inconsistency as to what exactly is meant by "stanza". I use it in the sense IBM uses it, i.e. in the file /etc/filesystems. It codes tabular data in the following form:

Code:
tablename1:
     column-name1=value1
     column-name2=value2
     column-name3=value3
     .....

tablename2:
     column-name1=value1
     column-name2=value2
     column-name3=value3
     .....

String values can be quoted to enclose white space like this:

Code:
tablename:
     string="value"
     .....

and i added the capability for inline- as well as line-comments which work the same way as in the shell: everything after an (unquoted and unescaped) comment sign ("#") up to the end of line is a comment. Notice that escaping needs to be done by double backslashes:

Code:
tablename:
     item=StringWith\\#EscapedChar
     .....


The Parser
The parser is done in a shell function which is callable. The function gets the following parameters:

1) the input file to parse

2) the name of a handler function. This function is called with every successfully parsed stanza and is passed three parameters: the table name and the name of two arrays, one contains the column names and one the respective values. Both arrays are 1-based.

3) An (optional) flag (0 or 1) to switch on or off "double-checking". Consider the following stanza where "item2" ismentioned two times:

Code:
table:
     item1=value1
     item2=value2
     item2=value3

This flag determines wether such a condition is considered to be wrong (an error is raised and the stanza is rejected) or not.

4) The name of an array which contains table/columnname combinations along with "data types", separated by colons (":"). If such an array is passed the mentioned table/columnn-combinations are checked for the value being of the correct data type. Notice that i use "data type" rather losely here. Right now allowed types are:

"file" - name of an existing file
"int" - an integer
"num" any numeric (float, only decimal notation)
"char" - any string

I plan to add more "data types" (i.e. a valid file name of a non-existing file) in a later revision, if you have ideas: just tell me. Here is a sample array definition and the subsequent call to the parser function:

Code:
typeset aTypes[1]="table1:field1:int"
typeset    aTypes[2]="table1:field2:num"
typeset    aTypes[3]="table1:field3:file"
typeset    aTypes[4]="table1:field4:char"
typeset -i lDblCheck=0

f_ProcessStanza /input/file pHandler $lDblCheck "aTypes"


The Handler Function
The function name passed to the parser must point to a valid function in your script. The function named there will be called with every successfully parsed stanza entry. Here is a template for how the function could look like:

Code:
#------------------------------------------ function pHandler
pHandler()
{
typeset -i iCnt=0
typeset    chTable=$1                      # records name
#typeset    aField                         # given by REFERENCE and
#typeset    aValue                         # holding field names/values


(( iCnt = 1 ))                             # extract record
while [ $iCnt -le $(eval print \${#$2[*]}) ] ; do
    typeset aField[$iCnt]=$(eval print \${$2[$iCnt]})
    typeset aValue[$iCnt]=$(eval print \${$3[$iCnt]})
    (( iCnt += 1 ))
done

case $chTable in
          .
          .
          .
          .   # process the different table types here
          .

     *)
          f_die 1 "error: unknown stanza entry $chTable"
          ;;

esac

return 0
}
#------------------------------------------ function pMain


Compatibility Issues

I have tested the parser only with ksh93 but it should work with ksh88 too as i see no reason why it shouldn't. Test it thoroughly before depending on it, though. For the whole to work in bash, though, some work is perhaps needed. There are some function used in there which come from my library. The names should make it pretty obvious what their purpose is. If there is interest in this i can provide the rest of my library.


The Code

Code:
# ------------------------------------------------------------------------------
# f_ProcessStanza                           parsing and processing stanza files
# ------------------------------------------------------------------------------
# Author.....: Wolf Machowitsch
# last update: 2018 12 10    by: Wolf Machowitsch
# ------------------------------------------------------------------------------
# Revision Log:
# - 0.99   1999 03 16   Original Creation
#                       Revision description
#
# - 1.00   1999 07 26   Production Release
#                       elaborated on the documentation, straightened out
#                       some minor glitches
#
# - 1.01   2000 01 01   Minor Revision
#                       straightened out faulty metacharacter expansion
#                       when content of $chLine resembles "*" and clarified
#                       the documentation
#
# - 2.00   2017 06 12   Major Update
#                       - new way of parsing implemented
#                       - makeover of old code
#                       - changed double-checking to be optional
#
# - 2.01   2018 12 10   type-checking
#                       - typechecking implemented, types are
#                         char  (practically everything)
#                         int   (integer)
#                         num   (numeric in any kind)
#                         file  (existing file)
#                         There should be: non-existing file.
#
# ------------------------------------------------------------------------------
# Usage:
#     f_ProcessStanza char File, char *Fnc, [ bool checkdbl, \
#                     [ char *Type[] ] ]
#
#     Reads and parses the stanza file given in $1 and calls a function
#     given in $2 to process the read records.
#
#     Example:
#              f_ProcessStanza /tmp/MyFile MyFunc 0 aFields aTypes
#
#              This causes the file '/tmp/MyFile' to be parsed. After
#              each record the function MyFunc() is called to process
#              the record read.
#
#      Additional checks are being performed after each line and after
#      each stanza is parsed and before the processing function is called.
#      Stanza entries failing these checks lead to an error message.
#
#     Double-checking
#     ===============
#     The third parameter (double-checking, allowed values are 0=off, 1=on)
#     checks for double entries within stanzas. When this check is off,
#     entries like:
#
#              ....
#              address:
#                   name="Smith"
#                   age=25
#                   income=1000.15
#                   income=2000.10
#
#      are allowed while enabling double-checking will lead to an error for
#      the fourth line. The line will be dropped, parsing will continue,
#      however.
#
#      Type-checking
#      =============
#      The types of the lines are typechecked using the array passed in the
#      fourth parameter. It has the structure of "tablename:fieldname:type"
#      and has to have one entry for every field of each record which is to
#      be checked. Field/table combinations are simply not checked at all.
#
#      Example:
#              ...
#              aTypes[1]="address:name:char"
#              aTypes[2]="address:age:int"
#              aTypes[3]="address:income:num"
#              aTypes[4]="address:notes:file"
#
#              f_ProcessStanza /tmp/MyFile MyFunc aFields aTypes
#              ...
#
#      In the above example only records with a table designator of 'address'
#      are checked. In every table-record the four fields, "name", "age",
#      "income" and "notes" are being typechecked:
#
#              "name"      has to have character content,
#              "age"       has to have integer content,
#              "income"    has to have number (float) content and
#              "notes"     has to contain a path name.
#
#      Example: the record
#
#              address:
#                   name="Smith"
#                   age=25
#                   income=1000.15
#                   notes=/path/to/notes.file
#
#      will be passed, whereas this:
#
#              address:
#                   name="Smith"
#                   age=25.1
#                   income=1000.15
#                   notes=/path/to/notes.file
#
#              will not because the content of "age" is allowed to be
#              of type integer only.
#
# Prerequisites:
# -   This function requires ksh93 to be used.
#
# -   The FPATH environment variable must be set to use this function.
#
# -   functional dependencies: f_CheckInteger(), f_CheckNumeric()
#
# ------------------------------------------------------------------------------
# Documentation:
#     Reads and parses the stanza file given in $1 and calls a function
#     given in $2 to process the read records.
#
#     Optionally a value of 0 or 1 can be passed as third parameter which
#     causes duplicate items in a single record to be dropped.
#
#     If an optional fourth parameter is supplied to f_ProcessStanza() the
#     types of fields read are being typechecked. The format of the fields
#     array entries is 'tablename:fieldname:type' where 'tablename' is the
#     name of the record designator and 'fieldname' is the name of the
#     field allowed in this type of record. Valid types are:
#
#              char: any alphanumerical string
#              int:  integer
#              num:  numerical (rational numbers)
#              file: a valid filename of an existing file (only
#                    'test -f' is used, the handler function will
#                    have to verify the accessability conditions
#                    itself)
#
#     The stanza file can contain comments (like in ksh-scripts introduced
#     by '#', which is masking everything until EOL), a literal '#' has to
#     be escaped by a preceding double backslash ('\\#'). Inside quoted
#     strings comment signs are ignored and used literally too. Trailing
#     and leading blanks are stripped but inside double-quoted strings they
#     are preserved.
#
#     The function referenced by the function pointer given in $2 has to
#     accept three parameters. In $1 the record designator (=table name) is
#     passed. In $2 the name of an array of field names is passed. In $3
#     the name of an array with field values is passed. An example for a
#     processing function could look like:
#
#     #------------------------------------------ function pMain
#     {
#     typeset -i iCnt=0
#     typeset    chTable=$1                      # records name
#     #typeset    aField                         # given by REFERENCE and
#     #typeset    aValue                         # holding field names/values
#
#
#     (( iCnt = 1 ))                             # extract record
#     while [ $iCnt -le $(eval print \${#$2[*]}) ] ; do
#         typeset aField[$iCnt]=$(eval print \${$2[$iCnt]})
#         typeset aValue[$iCnt]=$(eval print \${$3[$iCnt]})
#         (( iCnt += 1 ))
#     done
#
#     case $chTable in
#          .
#          .
#          .
#          .   # process the different table types here
#          .
#
#          *)
#               f_die 1 "error: unknown stanza entry $chTable"
#               ;;
#
#     esac
#
#     return 0
#     }
#     #------------------------------------------ function pMain
#
#     The parsing loop
#     ================
#     Notice that the strange formulation of the line parsing loop is
#     necessary because a naive
#
#            while [ -n "$chLine" ] ; do
#                 chChar="${chLine%${chLine#?}}"
#                 chLine="${chLine#?}"
#                 ....
#            done
#     would break with input containing escape chars. See the discussion
#     at https://www.unix.com/shell-programming-and-scripting/\
#               273239-possible-ksh93-bug-expanding-variables.html
#
#
#     Parameters: char file  char *function  [ char *array  char *array ]
#     Returns   : 0 on success, >0 otherwise:
#                 1: stanza file not available (not readable/non-existent)
#                 2: format error: no table designator for record
#                 3: format error: misformatted stanza field line
#                 4: field error: unknown field encountered
#                 5: type error: wrong data type for this field
#                 6: other (internal) error: (undetermined, mostly params)
#                 All of these errors will cause the process process to
#                 terminate.
# ------------------------------------------------------------------------------
# known bugs:
#
#     none
# ------------------------------------------------------------------------------
# .....................(C) 2017 Wolf Machowitsch ...............................
# ------------------------------------------------------------------------------

f_ProcessStanza ()
{

$chFullDebug

                                                 # internal variables
typeset -i iRetVal=0                             # return value
typeset -x fInFile="$1"                          # name of stanza file
typeset -x pProcessRecord="$2"                   # name of processing function
typeset -x chLine=""                             # buffer for a input file line
typeset -x achTables[1]=""                       # table with table names
typeset -x achFields[1]=""                       # table with field names
typeset -x achTypes[1]=""                        # table with field types
typeset -i lTypCheck=0                           # flag: field type checking
                                                 #    0=disabled
typeset -i lDblCheck=0                           # flag: check for double items
                                                 #    0=disabled (default)
typeset -i lDoubleCheckError=0                   # flag: double item encountered
                                                 #    0=unraised
typeset -i iLinCnt=1                             # line counter f. input file
typeset -i iCnt=0                                # general counter
typeset -x chTmp=""                              # general string
typeset    chMaskString='????????????????????'   # mask for string manipulation

                                                 # variables/flags for parsing
typeset -x chItem=""                             # fields name
typeset -x chValue=""                            # value of field read
typeset -x chTable=""                            # tables name of actual rec.
typeset -i lInQuotes=0                           # flag for being inside quotes
typeset -i lEsc=0                                # flag: this char is escaped
typeset -i lBeforeText=1                         # flag: not text on line so far
typeset -i lInComment=0                          # flag: inside comment
typeset -i lPastEqual=0                          # before/after an "=" sign
typeset    chResult=""                           # parsed part of the line
typeset    chBlankBuffer=""                      # blanks in parsed text go
                                                 # there first to eventually get
                                                 # trimmed
typeset -i iMaxTypeArr=$(eval print \${#$4[@]})  # number of elements in type
                                                 # array for type checking

                                                 # these are unset/set for
                                                 # every record
# achRecField[*]                                 # array w. field names
# achRecType[*]                                  # array w. data types
# achRecValue[*]                                 # array w. field data

                                                 # initialization phase
if [ -n "$3" ] ; then                            # double-item checking on/off
     if   [ "$3" == "1" ] ; then
          (( lDblCheck = 1 ))
     elif [ "$3" == "0" ] ; then
          :
     else
          f_CmdWarning "ignoring argument ${3}, only specify 0 or 1"
     fi
fi

if [ -n "$4" ] ; then                            # type checking array passed
     lTypCheck=1                                 # enable type checking
     (( iCnt = 1 ))
     while (( iCnt <= iMaxTypeArr )) ; do
          (eval "print - \${$4[$iCnt]}") |\
          IFS=':' read achTables[$iCnt] achFields[$iCnt] achTypes[$iCnt]
          case "${achTypes[$iCnt]}" in
               char|int|num|file)
                    ;;

               *)
                    f_CmdError "unknown type to check for: ${achTypes[$iCnt]}"
                    return 1
                    ;;

          esac
          (( iCnt += 1 ))
     done
fi

if [ ! -r $fInFile ] ; then                      # file available ?
     iRetVal=1
     return $iRetVal
fi

(( iLinCnt = 1 ))                                # init line counter
while read -r chLine ; do                        # main parsing loop
     chItem=""
     chValue=""

     lInQuotes=0
     lEsc=0
     lBeforeText=1
     lInComment=0
     lPastEqual=0
     chResult=""
     chBlankBuffer=""
                                                 # double mask if too short
     while [ ${#chLine} -gt ${#chMaskString} ] ; do
          chMaskString="${chMaskString}${chMaskString}"
     done

     # print - "\n-- Begin Line $iLinCnt \"$chLine\""

                                                 # main parsing loop
     while [ -n "$chLine" ] ; do
                                                 # this is to avoid problems
                                                 # with escaped strings, see
                                                 # documentation above
          chChar="${chLine%$(printf '%*.*s' $(( ${#chLine} - 1 )) \
                                            $(( ${#chLine} - 1 )) \
                                            "$chMaskString")}"
          chLine="${chLine#?}"

          # print - "   char: \"$chChar\""
          # print - "   Line: \"$chLine\""

          if (( lInComment )) ; then
               chChar=""
          fi
          case "$chChar" in
               "")
                    ;;

                " "|"   ")
                    if ! (( lBeforeText )) ; then # trimming blanks
                         chBlankBuffer="${chBlankBuffer}${chChar}"
                    fi
                    chChar=""
                    lEsc=0
                    ;;

               \\)
                    chChar=""
                    lEsc=1
                    ;;

               \#)
                    if (( lEsc + lInQuotes )) ; then
                         lEsc=0
                    else
                         chChar=""
                         lInComment=1
                    fi
                    ;;

               \")
                    if (( lInQuotes )) ; then
                         lInQuotes=0
                         chResult="${chResult}${chBlankBuffer}"
                         if (( lPastEqual )) ; then
                              chValue="${chValue}${chBlankBuffer}"
                         else
                              chItem="${chItem}${chBlankBuffer}"
                         fi
                    else
                         if [ -n "$chBlankBuffer" ] ; then
                              chResult="${chResult} "
                              if (( lPastEqual )) ; then
                                   chValue="${chValue} "
                              else
                                   chItem="${chItem} "
                              fi
                         fi
                         lInQuotes=1
                    fi
                    chChar=""
                    chBlankBuffer=""
                    lBeforeText=0
                    ;;

               =)
                    if (( lEsc + lInQuotes )) ; then
                         lEsc=0
                    else
                         chChar=""
                         chBlankBuffer=""
                         lBeforeText=1
                         lPastEqual=1
                    fi                    ;;

               *)
                    lEsc=0
                    lBeforeText=0
                    if (( lInQuotes )) ; then
                         chResult="${chResult}${chBlankBuffer}"
                         if (( lPastEqual )) ; then
                              chValue="${chValue}${chBlankBuffer}"
                         else
                              chItem="${chItem}${chBlankBuffer}"
                         fi
                    else
                         if [ -n "$chBlankBuffer" ] ; then
                              chResult="${chResult} "
                              if (( lPastEqual )) ; then
                                   chValue="${chValue} "
                              else
                                   chItem="${chItem}$ "
                              fi
                         fi
                    fi
                    chBlankBuffer=""
                    ;;

          esac
          chResult="${chResult}${chChar}"
          if (( lPastEqual )) ; then
               chValue="${chValue}${chChar}"
          else
               chItem="${chItem}${chChar}"
          fi

     done

     case "$chResult" in
          "")                                    # empty line, ignore
               ;;

          *:)                                    # new record starts
               if (( ${#achRecField[@]} > 0 )) ; then
                    $pProcessRecord "$chTable" achRecField achRecValue
                    (( iCnt = ${#achRecField[@]} ))
                    while (( iCnt >= 0 )) ; do
                         unset achRecField[$iCnt]
                         unset achRecValue[$iCnt]
                         (( iCnt -= 1 ))
                    done
               fi
               chTable="${chResult%:}"
               ;;

          *)                                     # item line
               if [ -n "$chValue" -a -n "$chItem" ] ; then
                    (( lCheckDoubleError = 0 ))  # check for double items
                                                 # lines in already read array
                    if (( lDblCheck )) ; then
                         (( iCnt = 1 ))
                         while [ \( $iCnt -le ${#achRecField[@]} \) -a \
                                 \( lCheckDoubleError -eq 0 \) \
                               ] ; do
                              if [ "$chItem" == "${achRecField[$iCnt]}" ] ; then
                                   f_CmdWarning "Line ${iLinCnt}: double item $chItem"
                                   (( lCheckDoubleError = 1 ))
                              else
                                   (( iCnt += 1 ))
                              fi
                         done
                    fi
                    if ! (( lCheckDoubleError )) ; then
                         typeset achRecField[$((${#achRecField[@]}+1))]="$chItem"
                         typeset achRecValue[$((${#achRecValue[@]}+1))]="$chValue"
                    fi
               else
                    f_CmdError "Line ${iLinCnt} badly formed: \"$chResult\""
               fi
               if (( lTypCheck )) ; then         # type checking enabled
                    (( iCnt = 1 ))
                    while (( iCnt <= ${#achTables[@]} )) ; do
                         if [ "${achTables[$iCnt]}" = "${chTable}"  -a \
                              "${achFields[$iCnt]}" = "$chItem" ] ; then
                              case "${achTypes[$iCnt]}" in
                                   char)
                                        ;;

                                   int)
                                        if ! f_CheckInteger "$chValue" ; then
                                             f_CmdError "bad type \"int\" in line $iLinCnt"
                                             return 4
                                        fi
                                        ;;

                                   num)
                                        if ! f_CheckNumeric "$chValue" ; then
                                             f_CmdError "type error \"num\" in line $iLinCnt"
                                             return 4
                                        fi
                                        ;;

                                   file)
                                        if ! [ -f "$chValue" ] ; then
                                             f_CmdError "type error \"file\" in line $iLinCnt"
                                             return 4
                                        fi
                                        ;;

                              esac
                         fi
                         (( iCnt += 1 ))
                    done
               fi
               ;;

     esac

     (( iLinCnt += 1 ))
done < "$fInFile"

$pProcessRecord "$chTable" achRecField achRecValue

return $iRetVal
}

# --- EOF f_ProcessStanza


Here is a sample script that shows how to use the function. The handler function only prints the name of the table and the items and their values. It should give an idea about how to use the whole construct, though:

Code:
#! /bin/ksh

pTest ()
{
typeset chTbl="$1"
# typeset aFld[]=
# typeset aVal[]=
typeset -i iCnt=1
typeset -i iMax=$( eval print \${#$2[@]} )

print - "--- inside pTest()"
print - "--- $chTbl"
while (( iCnt <= iMax )) ; do
     print - "    " $(eval print \${$2[$iCnt]} = \${$3[$iCnt]})
     (( iCnt += 1 ))
done

return 0
}

# main()
. ~/lib/f_env    # this brings in the library and sets the environment

typeset achTypeCheck[1]="value1:field4:char"
typeset achTypeCheck[2]="value1:field5:num"
typeset achTypeCheck[3]="value1:field6:file"

f_ProcessStanza ./input.stanza pTest 0 achTypeCheck
print - "function returned: $?"

exit 0

Here is a sample input file that shows what is possible:

Code:
# test stanza file

value1:
     field4="bla foo # bla"   # comment
     field5=25   # comment
     field6=/home/bakunin/.profile   # this file exists
     # field6=/does/not/exist          # this doesn't. Uncomment to get a parsing error raised

# comments can be placed here
value1:   # or here
     # even here
     field1 = bla foo \\# bla

     # empty lines do not hurt either
     field2        =          "bla foo" # whitespace before/after the assignment operator are ignored, also unquoted whitespace
field3 = "bla foo" # i usually indent properly for better readability but the parser does not rely on that

I did my best to test the code above. Still, test for yourself before you use it in a critical setting. If you find bugs: PLEASE TELL ME! I'll be glad to weed them out.

bakunin

Last edited by bakunin; 01-08-2019 at 04:47 AM.. Reason: typo
These 5 Users Gave Thanks to bakunin For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. OS X (Apple)

DFT using pure ksh ONLY!

DFT using pure ksh ONLY! Well ksh now has its own DFT without the aid of AWK. The SINE, COSINE and SQRT functions are in the code directly and NOT sourced. This is stand alone and requires nothing but ksh itself. Who would have even thought that this was possible until very recently? Thanks to... (0 Replies)
Discussion started by: wisecracker
0 Replies

2. Shell Programming and Scripting

How to extract entire stanza using awk?

Hello friends, I have a text file with lot of stanzas with each starting with "O-O-O. Sample file :- 1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Nf3 c5 8. Rb1 O-O 9. Be2 cxd4 10. cxd4 Qa5+ 11. Bd2 Qxa2 12. O-O Bg4 13. Bg5 h6 14. Be3 (8 Replies)
Discussion started by: prvnrk
8 Replies

3. Shell Programming and Scripting

EDI File Parser

I've one EDI file which is to be parsed into 7 different file. I managed to extract required segments for a file(HEADER) to a separate file(sample3.dat) and is given below. $ cat sample3.dat REF*EI*273543997~ REF*2U*HELLO~ REF*G2*77685|132~ CLM*1000*0.00***12>B>1*N*A*Y*I~ CN1*05~... (5 Replies)
Discussion started by: ashokv3
5 Replies

4. AIX

Fsize in default: stanza.

The default: stanza in /etc/security/limits is still set to 2097151 on fsize (max file size). I know tar had issues with large files but is there any other reasons for it? I'm thinking yes since it's still set to that by IBM. Cheers, DH (4 Replies)
Discussion started by: Devyn
4 Replies

5. Shell Programming and Scripting

File Parser

Hi need help parsing a file. I have tag fields and values in a file with delimiter |. sample records from the file listed below 8=value|9=value|35=value|49=value|56=value|34=value|50=value|48=value|10=value 8=value|9=value|35=value|49=value|56=value|34=value|51=value|48=value|10=value... (2 Replies)
Discussion started by: subramanian
2 Replies

6. Shell Programming and Scripting

KSH script to run other ksh scripts and output it to a file and/or email

Hi I am new to this Scripting process and would like to know How can i write a ksh script that will call other ksh scripts and write the output to a file and/or email. For example ------- Script ABC ------- a.ksh b.ksh c.ksh I need to call all three scripts execute them and... (2 Replies)
Discussion started by: pacifican
2 Replies

7. SuSE

ubuntu to pure debian

ok, im going to start off by saying i am a newbee so some of the stuff i say may not be right. but anyways, right now i am using ubuntu hardy for my main distrobution. i love it and all, but the main reason i switched to linux (besides drm and the blue screen i see on my comp about ten times a... (13 Replies)
Discussion started by: Texasone
13 Replies

8. Shell Programming and Scripting

selecting the stanza fields

Hi Friends, I have a stanza file as below : CuDv: name = "hdisk34" status = 0 chgstatus = 3 ddins = "scsidisk" location = "06-08-02" parent = "fscsi0" connwhere = "W_0" PdDvLn = "disk/fcp/mpioosdisk" CuDv: ... (1 Reply)
Discussion started by: vijaya2006
1 Replies

9. Shell Programming and Scripting

getting the stanza names if the pattern found

Hi Friends, I have a file as below : machine1: abc xyz qwerty machine2: jkl mno machine3: hhh kkk qwerty Now ...i need to find all the stanza names that have the pattern "qwerty'" in it...( i need to get the output as machine1 and machine3 since... (4 Replies)
Discussion started by: vijaya2006
4 Replies

10. UNIX for Dummies Questions & Answers

Where can i get pure unix?

Hi guys, I do know how tu use linux (actully slack), i do know that linux was made from unix. Where can i get the unix? is that possible? Does it have any driver? Help me plz! (2 Replies)
Discussion started by: Bstyle
2 Replies
Login or Register to Ask a Question