Hi there!

Usually, sed can be used in different ways, but most of the time we use it to match lines in a file against a fixed regexp. Some examples:

This replaces ocurrences of regexp for “foo”:

sed 's/regexp/foo/g' < myfile

This prints all lines that have “foo”, but will change the first “o” in the line for an “a”:

sed -n '/foo/s/o/a/p' < myfile

and so on…

But I tried to do a different thing, with no success: can I pass to sed a file with a bunch of regular expressions and test them against a fixed string? I tried to play with pattern space, hold space, with no success. It just seems impossible to use them (which would be the closest to “variables”) in search commands.

I know sed is Turing complete, but using it that way would maybe require to implement a regexp engine from scratch?

Thanks!

  • silas@lemmy.eco.brOP
    link
    fedilink
    English
    arrow-up
    3
    ·
    2 days ago

    Yeah, I ended up using awk, which solved my problem perfectly. I was just curious if I could do that with sed, but it seems too complicated. Thank very much, guys!

    • zero_spelled_with_an_ecks
      link
      fedilink
      English
      arrow-up
      1
      ·
      2 days ago

      Good call. I have no doubt sed could do it but I do doubt it in would be worth the time to figure it out vs just adding awk in there.

  • ccryx@discuss.tchncs.de
    link
    fedilink
    English
    arrow-up
    1
    ·
    2 days ago

    I know you asked about sed, but in case grep is fine, too:

    echo theString | grep -f <file with patterns>
    

    Not sure if there’s an output which pattern matched.

  • notabot@lemm.ee
    link
    fedilink
    English
    arrow-up
    1
    ·
    2 days ago

    What result do you need? Do you just nedd to know if one of the regexps matched the string, or do you need to know which one, or is it something else?

  • FizzyOrange
    link
    fedilink
    English
    arrow-up
    1
    arrow-down
    4
    ·
    2 days ago

    IMO if you’re doing something that complex you shouldn’t be using sed, but yeah you can probably do this something like:

    while read REGEX; do
      sed "$REGEX" << EOF
    your test string
    EOF
    done <list_of_regexes.txt
    

    I strongly recommend you don’t do that though. It will be absolutely full of quoting bugs. Instead write a script in a proper language to do it. I recommend Deno, or maybe even Rust.

    If you use Rust you can also use RegexSet which will be much faster (if you just want to find matches anyway). Here’s what ChatGPT made me. Not tested but it looks vaguely right.

    use regex::RegexSet;
    use std::fs::File;
    use std::io::{self, BufRead};
    use std::path::Path;
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        // Define the fixed input string
        let input_string = "This is a test string for regex matching.";
    
        // Path to the file containing the regexes
        let regex_file_path = "regexes.txt";
    
        // Read regexes from the file
        let regexes = read_lines(regex_file_path)?
            .filter_map(Result::ok) // Filter out errors
            .collect::<Vec<String>>();
    
        // Create a RegexSet from the regexes
        let regex_set = RegexSet::new(&regexes)?;
    
        // Find the regexes that match the input string
        let matches: Vec<_> = regex_set.matches(input_string).into_iter().collect();
    
        // Print the matches
        if matches.is_empty() {
            println!("No regexes matched the input string.");
        } else {
            println!("Regexes that matched the input string:");
            for index in matches {
                println!(" - {}", regexes[index]);
            }
        }
    
        Ok(())
    }
    
    // Helper function to read lines from a file
    fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
    where
        P: AsRef<Path>,
    {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines())
    }
    
    
    • freagle@lemmygrad.ml
      link
      fedilink
      English
      arrow-up
      1
      arrow-down
      1
      ·
      edit-2
      2 days ago

      Way over engineered.

      Both grep and sed take pattern files as input

      For sed, the -f flag

      -f script-file
      --file=script-file
      
      Add the commands contained in the file script-file to the set of commands to be run while processing the input.
      

      For grep, -f

      -f FILE, --file=FILE
      Obtain patterns from FILE, one per line.  If this option is used multiple times or is combined with the -e (--regexp) option, search for all patterns given.  The empty file contains zero patterns, and therefore matches nothing.  If FILE is - , read patterns from standard input.