Find a string and its position in a line from another string

Hello guys, would you please help me with this?

this is the line inside a file:

first line Something Today YYDDPPSVXIPYYY0XXXOFFS00000000000?

I'd like to find the position of string XXX from string PYYY

In the example above

XXX starts from 6th position from PYYY

desired result = 6

Another file, another line

TODAY YYDDPPSVXIPYYY000XXXOFFS00000

desired result = 8

==

Which command to use to find out the position of XXX from PYYY ?

Thanks a lot,
Marian

You could try something like:

awk 'match($0, /PYY.*XXX/){printf("%d %s\n", RLENGTH - 2, substr($0, RSTART, RLENGTH))}' file

which, if file contains the text found in post #1 in this thread, produces the output:

6 PYYY0XXX
8 PYYY000XXX

If you want to try this on a Solaris/SunOS system, change awk to /usr/xpg4/bin/awk or nawk .

1 Like

Try

awk '{print index ($0, STR2) - index ($0, STR1) + 1}' STR1="PYYY" STR2="XXX" file
6
8
1 Like

thanks a lot, it works :slight_smile:

Because i am a closet-show-off (and because the almighy Korn shell is really the only tool one ever needs ;-)) ) here is a solution in pure ksh , call it like ./script "string" "pattern" :

#! /bin/ksh

typeset    chStr="$1"
typeset    chPattern="$2"

typeset -i iStrIdx=1
typeset -i iPatLen=${#chPattern}
typeset -i iStrLen=$(( ${#chStr} - iPatLen + 1 ))

while [ $iStrIdx -le $iStrLen ] ; do
     if [ "${chStr#${chPattern}}" != "${chStr}" ] ; then
          print - "$chPattern found at position $iStrIdx"
          exit 0
     fi
     (( iStrIdx += 1 ))
     chStr="${chStr#?}"
done

print - "Pattern $chPattern not found in String"
exit 1

This script is supposed to be called with the string and the pattern on the command line. With the following slight modification it will work inside a pipeline instead, called like cat file | ./script "pattern" ( cat file represents any datastream here):

#! /bin/ksh

typeset    chPattern="$1"

typeset -i iStrIdx=1
typeset -i iPatLen=${#chPattern}
typeset -i iStrLen=0
typeset -i iLineCnt=0
typeset -i lFound=0

while read chStr ; do
     iStrIdx=1
     iStrlen=$(( ${#chStr} - iPatLen + 1 ))
     (( iLineCnt += 1 ))
     (( lFound = 0 ))
     while [ $iStrIdx -le $iStrLen ] ; do
          if [ "${chStr#${chPattern}}" != "${chStr}" ] ; then
               print - "$chPattern found at position $iStrIdx in line $iLineCnt"
               (( iStrIdx = iStrLen )) # skip rest of string
               (( lFound = 1 ))
          else
               (( iStrIdx += 1 ))
               chStr="${chStr#?}"
          fi
     done
     if ! (( lFound )) ; then
          print - "$chPattern not found in line $iLineCnt"
     fi
done

exit 0

To make the pattern equally dynamic as the input (i.e. the patterns to be read from a stream either) is left as an exercise to the reader.

I hope this helps.

bakunin