<p><em>I am assuming you want all keywords in a 'group' of keywords to be present in a single <strong>line</strong>, in order for you to extract that single line. If you want the keywords to be present in a single <strong>file</strong> to extract all text from that file, let me know so I can adjust the answer.</em></p>
<p>Indeed <code>pdfsearch::keyword_search()</code> searches only individual words. Luckily it does give us a page number and a line number for each result, so we can match those and check if all words from a single group are present in the search results on the same line:</p>
<h5>Preparation</h5>
<p>We start by defining our keywords grouped into vectors, and loading an example file:</p>
<pre class="lang-r prettyprint-override"><code>library(pdfsearch)
library(dplyr)

# Our list of keywords, grouped in vectors
grouped_keywords &lt;- list(c('saturated','model'),
                 c('vector','specification'),
                 c('framework','inferences'),
                 c('test','that','gives','no','results'),
                 c('population','degree','types'))

# Example file supplied with `pdfsearch`, also available at https://arxiv.org/pdf/1610.00147.pdf
file &lt;- system.file('pdf', '1610.00147.pdf', package = 'pdfsearch')
</code></pre>
<h5>Step 1: search all words individually</h5>
<p>To start the search, we perform <code>keyword_search()</code> on a flattened version of <code>grouped_keywords</code>. This will yield all results we want, but also many results we don't want (lines that only contain one or a few of the keywords in a group).</p>
<pre class="lang-r prettyprint-override"><code># Search for individual keywords
individual_results &lt;- keyword_search(file, 
                         keyword = unlist(grouped_keywords), # combine our keyword list into a single 1-dimensional vector
                         path = TRUE)

cat(nrow(individual_results), 'results for individual words\n')
head(individual_results, n=3)
</code></pre>
<p>Result:</p>
<pre class="lang-r prettyprint-override"><code>367 results for individual words

# A tibble: 3 × 5
  keyword   page_num line_num line_text token_text
  &lt;chr&gt;        &lt;int&gt;    &lt;int&gt; &lt;list&gt;    &lt;list&gt;    
1 saturated        5      112 &lt;chr [1]&gt; &lt;list [1]&gt;
2 saturated        5      114 &lt;chr [1]&gt; &lt;list [1]&gt;
3 saturated        5      119 &lt;chr [1]&gt; &lt;list [1]&gt;
</code></pre>
<h5>Step 2: Merge results for keywords in the same subgroup</h5>
<p>For each group of keywords, we look for results that have the same line number and the same page number, ánd that match all keywords in the group:</p>
<pre class="lang-r prettyprint-override"><code>combined_results &lt;- lapply(grouped_keywords, \(keyword_group) {
  
  individual_results %&gt;%
    filter(keyword %in% keyword_group) %&gt;%
    group_by(page_num, line_num) %&gt;%
    filter(length(unique(keyword)) == length(unique(keyword_group))) %&gt;%
    summarise(keywords = paste(keyword_group, collapse=' + '),
              line_text = line_text[1],
              token_text = token_text[1],
              .groups=&quot;keep&quot;)
  
})

# Merge list of tibbles to a single tibble
combined_results &lt;- do.call(rbind, combined_results)

# Output result
cat(nrow(combined_results), 'results for combined words\n')
combined_results
</code></pre>
<p>Result:</p>
<pre class="lang-r prettyprint-override"><code>8 results for combined words

# A tibble: 8 × 5
# Groups:   page_num, line_num [8]
  page_num line_num keywords                    line_text token_text
     &lt;int&gt;    &lt;int&gt; &lt;chr&gt;                       &lt;list&gt;    &lt;list&gt;    
1        5      112 saturated + model           &lt;chr [1]&gt; &lt;list [1]&gt;
2        5      114 saturated + model           &lt;chr [1]&gt; &lt;list [1]&gt;
3        5      119 saturated + model           &lt;chr [1]&gt; &lt;list [1]&gt;
4        7      184 saturated + model           &lt;chr [1]&gt; &lt;list [1]&gt;
5        5      124 vector + specification      &lt;chr [1]&gt; &lt;list [1]&gt;
6        2       32 framework + inferences      &lt;chr [1]&gt; &lt;list [1]&gt;
7        7      168 framework + inferences      &lt;chr [1]&gt; &lt;list [1]&gt;
8        7      187 population + degree + types &lt;chr [1]&gt; &lt;list [1]&gt;
</code></pre>
<hr />
<p><strong>Edit 19 July 2022:</strong></p>
<p>To get only exact matches, it's not enough to add the additional filter constrain which I previously described in the comments; we also need to process that filter rowwise:</p>
<pre><code>combined_results &lt;- lapply(grouped_keywords, \(keyword_group) {
  individual_results %&gt;%
    rowwise() %&gt;%
    filter(keyword %in% keyword_group, tolower(keyword) %in% tolower(unlist(token_text))) %&gt;%
    group_by(pdf_name, line_num) %&gt;%
    filter(length(unique(keyword)) == length(unique(keyword_group))) %&gt;%
    summarise(keywords = paste(keyword_group, collapse=' + '),
              line_text = line_text[1],
              token_text = token_text[1],
              .groups=&quot;keep&quot;)
  
})
</code></pre>
<p>The complete code, also using <code>keyword_directory()</code> instead of <code>keyword_search()</code> and matching case-insensitive, becomes:</p>
<pre><code># Preparation -------------------------------------------------------------

library(pdfsearch)
library(dplyr)

# Our list of keywords, grouped in vectors
grouped_keywords &lt;- list(c('individuals','model'),
                         c('information','abundance'),
                         c('individual','ranking'),
                         c('Test','That','Gives','No','Results'),
                         c('population','degree','types'))

grouped_keywords &lt;- lapply(grouped_keywords, tolower)

# Directory containing a few example PDFs:
# https://arxiv.org/pdf/2207.00011.pdf
# https://arxiv.org/pdf/2207.00039.pdf
# https://arxiv.org/pdf/2207.00076.pdf
directory &lt;- &quot;~/Desktop/Rtemp/pdf/&quot;


# Search for individual keywords ------------------------------------------

individual_results &lt;- keyword_directory(directory, 
                                        keyword = unlist(grouped_keywords), # combine our keyword list into a single 1-dimensional vector
                                        split_pdf = TRUE)


cat(nrow(individual_results), 'results for individual words\n')
View(individual_results)


# Merge results for keywords in the same subgroup and file ----------------

combined_results &lt;- lapply(grouped_keywords, \(keyword_group) {
  individual_results %&gt;%
    rowwise() %&gt;%
    filter(keyword %in% keyword_group, tolower(keyword) %in% tolower(unlist(token_text))) %&gt;%
    group_by(pdf_name, line_num) %&gt;%
    filter(length(unique(keyword)) == length(unique(keyword_group))) %&gt;%
    summarise(keywords = paste(keyword_group, collapse=' + '),
              line_text = line_text[1],
              token_text = token_text[1],
              .groups=&quot;keep&quot;)
  
})

# Merge list of tibbles to a single tibble
combined_results &lt;- do.call(rbind, combined_results)

# Output result
cat(nrow(combined_results), 'results for combined words\n')
combined_results
</code></pre>
<pre><code>&gt; combined_results
# A tibble: 4 × 5
# Groups:   pdf_name, line_num [4]
  pdf_name       line_num keywords                line_text token_text
  &lt;chr&gt;             &lt;int&gt; &lt;chr&gt;                   &lt;list&gt;    &lt;list&gt;    
1 2207.00039.pdf      299 individuals + model     &lt;chr [1]&gt; &lt;list [1]&gt;
2 2207.00076.pdf        4 individuals + model     &lt;chr [1]&gt; &lt;list [1]&gt;
3 2207.00076.pdf       16 individuals + model     &lt;chr [1]&gt; &lt;list [1]&gt;
4 2207.00039.pdf       10 information + abundance &lt;chr [1]&gt; &lt;list [1]&gt;
</code></pre>
<p>You'll notice I also added <code>split_pdf = TRUE</code> to the <code>keyword_directory()</code>-call, to improve handling of multi-column PDFs. I have also removed matching on the page number; matching on line number alone is enough.</p>
Search combined keywords in a pdf with R
<p>I have a list of keywords to find text in a group of PDF files, some of the keyword must appear combined to extract the text even if they are not together.</p>
<p>I used the pdfsearch library and it finds text with the separated keywords. I read the documentation but I am not able to find a way to combine the keywords.</p>
<p>My code is as shown below:</p>
<pre><code>
    library(pdftools)
    library(pdfsearch)
    
    keywords &lt;- c(&quot;LOTE&quot;,&quot;VOLUMEN&quot;,
    &quot;LOTE&quot;,&quot;SOLVENCIA&quot;,
    &quot;LOTE&quot;,&quot;SEGURO&quot;,
    &quot;VOLUMEN&quot;,&quot;TRES ÚLTIMOS&quot;,
    &quot;VOLUMEN&quot;,&quot;3 ÚLTIMOS&quot;,
    &quot;VOLUMEN&quot;,&quot;(3) ÚLTIMOS&quot;,
    &quot;NO&quot;, &quot;APLICA&quot;, &quot;SOLVENCIA&quot;)
    
    Results &lt;- keyword_directory(directory,
                                            keyword = keywords,
                                            surround_lines = 1, full_names = TRUE, 
                                            ignore_case = TRUE, remove_hyphen = TRUE)

</code></pre>
<p>In the keyword assignation, every line is a combination:</p>
<pre><code>&quot;LOTE&quot; + &quot;SOLVENCIA&quot;,
&quot;LOTE&quot; + &quot;SEGURO&quot;,
&quot;VOLUMEN&quot; + &quot;TRES ÚLTIMOS&quot;,
&quot;VOLUMEN&quot;+ &quot;3 ÚLTIMOS&quot;,
&quot;VOLUMEN&quot; + &quot;(3) ÚLTIMOS&quot;,
&quot;NO&quot; + &quot;APLICA&quot; + &quot;SOLVENCIA&quot;
</code></pre>
<p>For example the combination &quot;NO&quot; + &quot;APLICA&quot; + &quot;SOLVENCIA&quot;</p>
<p>This text should be extracted
&quot;No siempre aplica el uso de solvencia para el proyecto&quot;</p>
<p>This text should no be extracted even if it has the keyword &quot;NO&quot;
&quot;No pueden contar con las listas antes de tiempo&quot;</p>
<p>At the moment I am able just to get the text where the separated keyword appear.</p>