julia to regex match lines in a file like grep

Viewed 1829

I would like to see a code snippet of julia that will read a file and return lines (string type) that match a regular expression.

I welcome multiple techniques, but output should be equivalent to the following:

$> grep -E ^AB[AJ].*TO' 'webster-unabridged-dictionary-1913.txt'

ABACTOR
ABATOR
ABATTOIR
ABJURATORY

I'm using GNU grep 3.1 here, and the first line of each entry in the file is the all caps word on its own.

3 Answers

My favored solution uses a simple loop and is very easy to understand.

julia> open("webster-unabridged-dictionary-1913.txt") do f
           for i in eachline(f)
               if ismatch(r"^AB[AJ].*TO", i) println(i) end
           end
       end

ABACTOR
ABATOR
ABATTOIR
ABJURATORY

notes

  • Lines with tab separations have the tabs preserved (no literal output of '\t')
  • my source file in this example has the dictionary words in all caps alone on one line above the definition; the complete line is returned.
  • the file I/O operation is wrapped in a do block syntax structure, which expresses an anonymous function more conveniently than lamba x -> f(x) syntax for multi-line functions. This is particularly expressive with the file open() command, defined with a try-finally-close operation when called with a function as an argument.
  • Julia docs: Strings/Regular Expressions
    • regex objects take the form r"<regex_literal_here>"
    • the regex itself is a string
    • based on perl PCRE library
    • matches become regex match objects

example

julia> reg = r"^AB[AJ].*TO";
julia> typeof(reg)
Regex

julia> test = match(reg, "ABJURATORY")
RegexMatch("ABJURATO")

julia> typeof(test)
RegexMatch

You could also use the filter function to do this in one line.

filter(line -> ismatch(r"^AB[AJ].*TO",line),readlines(open("webster-unabridged-dictionary-1913.txt")))

filter applies a function returning a Boolean to an array, and only returns those elements of the array which are true. The function in this case is an anonymous function line -> ismatch(r"^AB[AJ].*TO",line)", which basically says to call each element of the array being filtered (each line, in this case) line.

I think this might not be the best solution for very large files as the entire file needs to be loaded into memory before filtering, but for this example it seems to be just as fast as the for loop using eachline. Another difference is that this solution returns the results as an array rather than printing each of them, which depending on what you want to do with the matches might be a good or bad thing.

Just putting ; in front is Julia's way to using commandline commands so this works in Julia's REPL

;grep -E ^AB[AJ].*TO' 'webster-unabridged-dictionary-1913.txt'
Related