1

I have a very long string and I want to find the first occurrence of a substring - but the substring contains double quotes. The only way of doing this that I'm familiar with is:

mystr='a very, very, extremely, incredibly long string of text that contains the phrase he said, "Hello!" somewhere in the middle'
strpos=`expr index "$mystr" Hello`
echo $strpos

which returns 92. But that won't work if the substring contains double quotes...

strpos=`expr index "$mystr" he said, "Hello`

I've tried escaping the double quotes (and the spaces). I've tried wrapping the string to find with single quotes. If I manage to run it without getting "unexpected EOF" or "syntax error", it returns a preposterous result like "2". (The position is somewhere in the thousands.) I'm guessing that I can't do what I'm trying to do with expr index but if not, then how can I do it?

2
  • Just to clarify, I'm not trying to echo "Hello!". I'm trying to get just the starting position of the substring within the main string - and have that number assigned to a variable. Jan 28, 2021 at 4:55
  • the expr man page says index STRING CHARS gives the "index in STRING where any CHARS is found, or 0". That is, it looks for any of the given characters, not a full substring. expr index foobar bo gives 2 (the first o), expr index 'foo"bar' '"' gives 4 (the first quote) and expr index 'foo"bar' '"foo"' gives 1 (the very first f). What are you trying to do in the end? There might be some other way to do that without getting the actual position of the substring.
    – ilkkachu
    Jan 28, 2021 at 20:26

3 Answers 3

2

I think that it searches for characters of second string in first one. You can use grep

mystr='a very, very, extremely, incredibly long string of text that contains 2 the phrase he said, "Hello!" somewhere in the middle'
echo "$mystr"| grep -o -b Hello!

It will return 91:Hello!. Here indexing starts from 0.

If there are multiple occurrences like of a, then output will be

0:a 58:a 65:a 77:a 85:a

If you want to search double quotes too, then escape them,

echo "$mystr"| grep -o -b \"Hello!\"

The output will be

90:"Hello!"
1
  • This will fail if there's another "Hello!" in the string, as OP's requirement is the first occurrence. You can use then head -1 to get it. I'm borrowing the -b for my answer :) Jan 28, 2021 at 4:51
2

Only with Parameter Expansion :

mystr='a very, very, extremely, incredibly long string of text that contains the phrase he said, "Hello!" somewhere in the middle'  
searchstr='"Hello!"'
newstr="${mystr%%$searchstr*}"
echo "position = $((${#newstr} + 1))"
1
  • This is the optimal one liner answer
    – Brethlosze
    Apr 4, 2023 at 0:30
1

Let's see if this is what you are looking for:

mystr='a very, very, extremely, incredibly long string of text that contains the phrase he said, "Hello!" somewhere in the middle'

$ var=$(echo "$mystr" | grep -o -b "Hello!" | head -1)
$ echo "$var"
91:Hello!
$ pos="${var%:*}"
$ echo "$pos"
91
3
  • What does 'head -1' do? because there are 30 occurrences of the substring within the main string. Your code finds the 29th one. Jan 28, 2021 at 6:01
  • head -1 prints the first result of the grep command. If in your case it doesn't there must be something different in the string and/or the command. Is the real string too long? If not, you can post it along with the command you used. Jan 28, 2021 at 6:11
  • Nope, it's all good. The occurences got reordered so it's working properly. Thanks for the help! Jan 28, 2021 at 16:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .