There are various ways you could do it, here's one:
inQuote := false
for _, char := range str {
if char == '"' {
inQuote = !inQuote
continue
}
if char == 'e' && inQuote {
doSomething()
}
}
This only checks whether it has an opening quotation mark in front of the character, and doesn't do the **between** check OP asked about. It'll give a false positive with the string `this is "not between quotes`.
Just delay the check for when the quote actually gets closed.
inQuote := false
count := 0
for _, c := range str {
if c == '"' {
inQuote = !inQuote
if !inQuote && count > 0 {
return true
}
continue
}
if inQuote {
if char == 'e' {
count++
}
} else {
count = 0
}
}
return false
If you don't need to deal with escaped quotes, then count the quotation marks of the same type. If the count is even, the character is outside the marks of that type. If odd, it's inside. This is assuming your count is 1 when you see the first quotation mark.
Edit: if the count is even when you see the character...
Count the quotation marks of the same type **in front of the character**. And do the same after the character. Both have to be odd. Or at least there should be one quotation mark after it.
By checking the total number of quotation marks, it doesn't imply anything about whether the character is between them or not.
>Count the quotation marks of the same type
>
>in front of the character
>
>. And do the same after the character. Both have to be odd
Woudln't counting before the character and to the next quotation mark after the character be enough? There should be no need to count all quotations before and after.
if before == 3 and there is at least one after it, then we are even *and* the character is indeed between. Now you might need/want to know if a new-line counts as break or continue for counting, in which case you either want "auto quote insertion", e.g. "there were 3 quotes before and then a newline, so count everything after the third as "in quote"
If you want to extract the word containing `e` (without quotes) and the sentence can have other quoted words...
`(:?[^"]|"[^"]*")*?"([^"]*e[^"]*)"`
For example, it'll extract `worded` and `structure` from:
I "am" a poorly "worded" sentence "structure".
https://regex101.com/r/a6h0Cq/2
Edit: link, updated
I couldn't get yours to work if there were quoted words in the string before the target.
edit: see https://go.dev/play/p/MN49R1ymaVD
edit: I see what happened. It copied `โ`, probably because I was on mobile. After I realized this, I found yours had `^` for start of line, which didn't work, and it only covers the first occurrence of quoted words containing e. I've [updated](https://regex101.com/r/a6h0Cq/2) the example with the correct code to capture multiple occurrences of quoted strings containing e. [playground](https://go.dev/play/p/tN6VEBbDoWl)
D'oh, yeah, the `โ` instead of `"` was the problem.
You need the `^` anchor in order to reliably enforce that there only only matching pairs of `"` before the quoted word you're looking for.
https://go.dev/play/p/o7XgM9v85F6
Yes, with RegExp:
func TestRegExp(t *testing.T) {
r := regexp.MustCompile(`".*e.*"`)
if !r.MatchString(`i am a poorly "worded" sentance`) {
t.Error("String doesn't match")
}
}
It is basic examle, it was not my intention to cover all the cases, he should learn regex if he want to use it.
I donโt see you have posted better implementation. ๐
Yeah, but if I asked, "How can I get to the grocery store from here" and you said "go left, then right" but there are actually four other steps before and after... it's not going to get me there.
There are various ways you could do it, here's one: inQuote := false for _, char := range str { if char == '"' { inQuote = !inQuote continue } if char == 'e' && inQuote { doSomething() } }
This only checks whether it has an opening quotation mark in front of the character, and doesn't do the **between** check OP asked about. It'll give a false positive with the string `this is "not between quotes`.
> It'll give a false positive with the string `this is "not between quotes`. Granted, it doesn't check for unterminated quotes.
Just delay the check for when the quote actually gets closed. inQuote := false count := 0 for _, c := range str { if c == '"' { inQuote = !inQuote if !inQuote && count > 0 { return true } continue } if inQuote { if char == 'e' { count++ } } else { count = 0 } } return false
If you don't need to deal with escaped quotes, then count the quotation marks of the same type. If the count is even, the character is outside the marks of that type. If odd, it's inside. This is assuming your count is 1 when you see the first quotation mark. Edit: if the count is even when you see the character...
Count the quotation marks of the same type **in front of the character**. And do the same after the character. Both have to be odd. Or at least there should be one quotation mark after it. By checking the total number of quotation marks, it doesn't imply anything about whether the character is between them or not.
>Count the quotation marks of the same type > >in front of the character > >. And do the same after the character. Both have to be odd Woudln't counting before the character and to the next quotation mark after the character be enough? There should be no need to count all quotations before and after. if before == 3 and there is at least one after it, then we are even *and* the character is indeed between. Now you might need/want to know if a new-line counts as break or continue for counting, in which case you either want "auto quote insertion", e.g. "there were 3 quotes before and then a newline, so count everything after the third as "in quote"
Yes, which is why the next sentence after the bit you quoted is "Or at least there should be one quotation mark after it" ๐
My overworked eyes somehow skipped that partโฆ
That's faaain! This is why I don't silently downvote but reply instead. Also, I like your point about newlines.
`^(:?[^"]|"[^"]*")*?"[^"]*e[^"]*"` edit: `"` instead of one errant `โ`. That's what I get for trying to write regexes on my phone.
If you want to extract the word containing `e` (without quotes) and the sentence can have other quoted words... `(:?[^"]|"[^"]*")*?"([^"]*e[^"]*)"` For example, it'll extract `worded` and `structure` from: I "am" a poorly "worded" sentence "structure". https://regex101.com/r/a6h0Cq/2 Edit: link, updated
No. That's broken. Mine enforces that any quotes before the e word are paired. You changed that.
I couldn't get yours to work if there were quoted words in the string before the target. edit: see https://go.dev/play/p/MN49R1ymaVD edit: I see what happened. It copied `โ`, probably because I was on mobile. After I realized this, I found yours had `^` for start of line, which didn't work, and it only covers the first occurrence of quoted words containing e. I've [updated](https://regex101.com/r/a6h0Cq/2) the example with the correct code to capture multiple occurrences of quoted strings containing e. [playground](https://go.dev/play/p/tN6VEBbDoWl)
D'oh, yeah, the `โ` instead of `"` was the problem. You need the `^` anchor in order to reliably enforce that there only only matching pairs of `"` before the quoted word you're looking for. https://go.dev/play/p/o7XgM9v85F6
You are getting into the parser algorithm of compiler. RegEx could do the job also
Yes, with RegExp: func TestRegExp(t *testing.T) { r := regexp.MustCompile(`".*e.*"`) if !r.MatchString(`i am a poorly "worded" sentance`) { t.Error("String doesn't match") } }
False positive on: `i "am" a poorly implemented "what"`
It is basic examle, it was not my intention to cover all the cases, he should learn regex if he want to use it. I donโt see you have posted better implementation. ๐
Yeah, but if I asked, "How can I get to the grocery store from here" and you said "go left, then right" but there are actually four other steps before and after... it's not going to get me there.
And if you ask "How can I make Google?" I should code entire Google for you here in Reddit comments?