2

I need to print a list of files with match a specific pattern -- a string occurring between two other strings. How do I do that. I don't want to extract text, just list the files that match this pattern.

I need a command that will match and list all filenames which contain an instance of the string PREFETCH which occurs somewhere between these two strings: advanced_override.begin and advanced_override.end. The files are all present in the same directory, so the command should search the contents of the current directory '.' and list the filenames which match the specified pattern.

UPDATE:

It must have something like this: advanced_override.begin <lots of text> PREFTECH <lots of other text> advanced_override.end. I need it to match this string somewhere between those two strings and there can be lots of other text before or after PREFETCH.

UPDATE TWO:

The input files are XML files. And the section beginning with advanced_override.begin and advanced_override.end can be large with many lines of text.

closed as off-topic by Kusalananda, Jeff Schaller, roaima, Christopher, Michael Homer Feb 21 at 5:06

  • This question does not appear to be about Unix or Linux within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

  • You mean filename or the file content? – cuonglm Jun 6 '16 at 16:30
  • Yes. I want to list the filenames. – Selena Jun 6 '16 at 16:31
  • 4
    Please provide examples of input and desired outputs -- otherwise we're just guessing – KM. Jun 6 '16 at 16:34
  • 3
    Before you head off in the wrong direction of regexps: Don't parse XML or HTML with regular expressions. It doesn't work. if you have to do it in sh, use something like xmlstarlet, otherwise both perl and python have excellent library modules for parsing XML. – cas Jun 7 '16 at 3:40
  • 2
    I'm voting to close this question as off-topic because it asks about parsing a specific XML document without revealing what the document structure looks like. Any answer would be guesswork, even if a proper XML parser was used. – Kusalananda Feb 19 at 19:20
1

You could use pcregrep if available, with the -l switch, to only list the names of files that match:

pcregrep -lM '(?s)advanced_override\.begin.*PREFETCH.*advanced_override\.end' ./*

This searches in multiline mode for those two strings with PREFETCH in between. It assumes there are only text files in the current directory (if that's not the case you could use a for loop or find) and also that each file contains a single section that starts with advanced_override.begin and ends with advanced_override.end - with multiple sections it may be better to use a negative lookahead before PREFETCH e.g.:

pcregrep -lM '(?s)advanced_override\.begin(?:(?!advanced_override\.end).)*PREFETCH.*advanced_override\.end' ./*
  • Unfortunately this does not work for me. I have a Mac and can't seem to find a version of this utility for mac. – Selena Jun 8 '16 at 13:41
  • After installing Homebrew (brew.sh), brew install pcre provides pcregrep. – Christopher Feb 20 at 14:39
0

The above warnings, here and here, but especially here about trying to parse XML files with regular expressions are well-heeded. In general, XML text may not be confined to a single line, but since in this case you're searching for specific single words, and on the assumption that they are not themselves broken apart to multiple lines, you could use a simple awk script that keeps "state". If it sees the next expected word, it increments the state value. If it finds all of the expected patterns in the right order, it sets a found variable which we then base a return code off of:

#!/bin/sh
for f in *
do
  awk '
/advanced_override\.begin/ { state=1; }
/PREFETCH/ && state == 1 { state=2; }
/advanced_override\.end/ && state == 2 { found=1; }
END {
  if (found)
    exit 0
  else
    exit 1
}
' "$f" && printf "Found in: %s\n" "$f"
done

Given these 3 sample input files:

$ cat input1
junk
advanced_override.begin other text
other text
PREFETCH other text
other text
advanced_override.end

$ cat input2
just some stuff
advanced_override.end

$ cat input3
junk
advanced_override.begin other text other text PREFETCH other text other text advanced_override.end
junk

A sample run of the script produces:

Found in: input1
Found in: input3

Not the answer you're looking for? Browse other questions tagged or ask your own question.