How to query lines with "string2" inside files with "string1"

Things I have tried

I searched in help docs about queries but couldn’t find a concrete solution for this.

I tried this without having a clean result:

string1 line:string2
(content:string1) (line:string2)
(content:string1) AND (line:string2)
(line:string2 (content:string1)) 

What I’m trying to do

I want that within the notes containing a specific string it shows me the lines containing another string.

3 Likes

Good question! I tried a few that I thought would work and didn’t get the results I imagined I would. I am definitely going to try to sit down and figure this out tomorrow because assumed this would have been pretty easy to accomplish in ways similar to the ones you showed.

In the meantime, one workaround would be to use the following regular expression as a search:

/string1.*string2|string2.*string1/

It isn’t going to bring you right to the line you want, but the line you want will be at the beginning or end of the matched text. I am new to regex so this might not even work the way I think, if at all, but it might be a start.

I look forward to seeing how this can be accomplished in a more elegant way.

Good luck! Thanks!

4 Likes

Mmmm, looks like this line doesn’t work in my vault/Obsidian.

1 Like

It’s for me not quite clear what you want. The term “line” doesn’t exist, therefore you can’t match a “line”. You can match a paragraph or a sentence but no line. Obsidian uses the term “line”, but I think the meaning is paragraph.

Two examples

  • query: foo ipsum

    • Files which contain “foo” and “ipsum”.
    • Selects “foo” and “ipsum”.
  • query: foo /^.*?ipsum.*/

    • Files which contain “foo” and “ipsum”.
    • Selects “foo” and paragraphs including “ipsum”.
1 Like

A line is anything between 2 newlines (returns), and Obsidian has a search operator for it.

Both of your examples select too many items. They want to select only 1 item, in files that contain the other.

1 Like

As far as I know this isn’t possible (aside from @I-d-as’s workaround), but I’d love to be wrong.

Another person asked about the same thing:

3 Likes

@CawlinTeffid , does the @I-d-as’ solution work for you? I don’t know if I’m doing something wrong.

1 Like

@AMGMNPLK You are right. It doesn’t work. When I tested the regex, I didn’t look carefully enough at the results to realize that it only works when both string1 and string2 are on the same line. @CawlinTeffid had actually mentioned something on a different thread about Obsidian’s regex possibly being based on lines. And, I guess if this is any indication, it is.

I meant to test things further or at least respond yesterday when I saw that you mentioned it hadn’t worked. Sorry it has taken me so long. I’ll let you know if I can get something working. It is definitely worth trying to figure out.

Thanks.

2 Likes

Here’s a modification of @I-d-as’s workaround that selects across >1 line:

/string1.*(.*\n)*.*string2|string2.*(.*\n)*.*string1/

It will select from the first string1 to the last string2 (and vice-versa), so you won’t see individual results for any occurrences of string2 between them.

I believe this modification using “lookahead/lookbehind assertions” would fulfill @AMGMNPLK’s entire request, but it freezes Obsidian:

/(?<=string1.*(.*\n)*.*)string2|string2(?=.*(.*\n)*.*string1)/

I guess it checks too big a number of possibilities. I’m trying to find a way to make it work.

2 Likes

Another (convoluted) approach might be to search string1, copy the results, and run some kind of macro to search string2 using each of the string1 results in a path: selector.

Obviously a built-in syntax would be better, or a way to chain searches (like a pipe in shell scripting).

1 Like

“it checks too big a number of possibilities”

Yes, that’s the problem, Regular Expressions are expensive and therefore I see - only with Regular Expressions - no (good) solution for that.

It is possible, but it lasts too long. The following should work. It’s just an example, without some special cases or a lookbehind as an alternation. It will freeze but if you wait you’ll get a result.

/((?<=foo[\s\S\n\r]*?)^.*?ipsum.*)+/

A solution would be, to collect the files containing foo with a simple string function and then a simple RegEx as in the query I posted before.

query: foo /^.*?ipsum.*/

“and run some kind of macro”

Good idea, I don’t think it’s “convoluted”, in the contrary. As far as I know (but I don’t no how) it’s possible to run macros (->shell commands) or JavaSript files inside Obsidian (maybe with Templater or Dataview).

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.