%% @author Anatolii Kosorukov [rustkas.github.io/] %% @copyright 2021 by Anatolii Kosorukov %% @doc Helper function for working with Regular Expression Erlanb re module. -module(re_tuner). -export([tune/1, avoid_characters/0, save_pattern/1, replace/1]). %% @doc Replace Regex pattern to more siple one. %% @returns Transformed Regex pattern. -spec tune(Regex) -> Result when Regex :: string(), Result :: string(). % \s tune("\\s") -> "[ \\t\\n\\r]"; % [^\s] tune("[^\\s]") -> "[^ \\t\\n\\r]"; % \w tune("\\w") -> "[0-9_a-zA-Z]"; % [^\w] tune("[^\\w]") -> "[^0-9_a-zA-Z]"; % \h tune("\\h") -> "[\\x9,\\x20]"; % [^\h] tune("[^\\h]") -> "[\\0-\\x8\\xA-\\x1F\\x21-x7F]"; % \v tune("\\v") -> "[\\xA-\\xD]"; % [^\h] tune("[^\\v]") -> "[\\0-\\x9\\xE-x7F]"; % Posix [[:alnum:]] tune("[[:alnum:]]") -> "[\\x30-\\x39\\x41-\\x5A\\x61-\\x7A]"; % Posix [[:^alnum:]] tune("[[:^alnum:]]") -> "[\\0-\\x29\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7F]"; % Posix [[:alpha:]] tune("[[:alpha:]]") -> "[\\x41-\\x5A\\x61-\\x7A]"; % Posix [[:^alpha:]] tune("[[:^alpha:]]") -> "[\\0-\\x40\\x5B-\\x60\\x7B-\\x7F]"; % Posix [[:lower:]] tune("[[:lower:]]") -> "[\\x61-\\x7A]"; % Posix [[:^lower:]] tune("[[:^lower:]]") -> "[\\0-\\x60\\x7B-\\x7F]"; % Posix [[:upper:]] tune("[[:upper:]]") -> "[\\x41-\\x5A]"; tune("[[:^upper:]]") -> "[\\0-\\x40\\x5B-\\xF7]"; % Posix [[:digit:]] tune("[[:digit:]]") -> "[\\x30-\\x39]"; tune("[[:^digit:]]") -> "[\\0-\\x29\\x3A-\\x7F]"; % Posix [[:graph:]] tune("[[:graph:]]") -> "[\\x21-\\x7E]"; tune("[[:^graph:]]") -> "[\\0-\\x20\\x7F]"; % Posix [[:print:]] tune("[[:print:]]") -> "[\\x20-\\x7E]"; tune("[[:^print:]]") -> "[\\0-\\x1F\\x7F]"; % Posix [[:punct:]] tune("[[:punct:]]") -> "[\\x21-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7E]"; tune("[[:^punct:]]") -> "[\\0-\\x20\\x30-\\x39\\x41-\\x5A\\x61-\\x7A\\x7F]"; % Posix [[:space:]] tune("[[:space:]]") -> "[\\x9-\\xD\\x20]"; tune("[[:^space:]]") -> "[\\0-\\x8\\xE-\\x1F\\x21-\\x7F]"; % Posix [[:cntrl:]] tune("[[:cntrl:]]") -> "[\\0-\\x1F]"; tune("[[:^cntrl:]]") -> "[\\x20-\\x7F]"; % Posix [[:ascii:]] tune("[[:ascii:]]") -> "[\\0-\\x7F]". %% @doc The list of characters which raise an error if escape character is not used. %% @returns The list of spectial characters. -spec avoid_characters() -> Result when Result :: string(). avoid_characters() -> "*.^$|{}]\-". %% @doc Make save Regex pattern which make literal for any character. %% @returns Save pattern -spec save_pattern(Pattern) -> SavePattern when Pattern :: string(), SavePattern :: string(). save_pattern(Pattern) -> "\\Q" ++ Pattern ++ "\\E". %% @doc Replace one of shorthand pattern from the list `[\s,\w,\h,v]' %% in a pattern string. %% @param Pattern searched regex pattern for replacing %% @returns Updated Regex pattern string -spec replace(Pattern) -> UpdatedPattern when Pattern :: string(), UpdatedPattern :: string(). replace(Pattern) -> CheckedShorthandsPlus = [% \s {"\\x{5c}s(?=\\+)", "[ \\\\t\\\\n\\\\r]"}, % \w {"\\x{5c}w(?=\\+)", "[0-9_a-zA-Z]"}, % \h {"\\x{5c}h(?=\\+)", "[\\\\x9\\\\x20]"}, % \v {"\\x{5c}v(?=\\+)", "[\\\\xA-\\\\xD]"}], UpdatedPatternPlus = lists:foldl(fun(Elem, Acc) -> Regex = element(1, Elem), Markup = element(2, Elem), NewContent = re:replace(Acc, Regex, Markup, [global, {return, list}]), NewContent end, Pattern, CheckedShorthandsPlus), CheckedShorthandsQuestionMark = [% \s {"\\x{5c}s(?=\\?)", "[ \\\\t\\\\n\\\\r]"}, % \w {"\\x{5c}w(?=\\?)", "[0-9_a-zA-Z]"}, % \h {"\\x{5c}h(?=\\?)", "[\\\\x9\\\\x20]"}, % \v {"\\x{5c}v(?=\\?)", "[\\\\xA-\\\\xD]"}], UpdatedPatternQuestionMark = lists:foldl(fun(Elem, Acc) -> Regex = element(1, Elem), Markup = element(2, Elem), NewContent = re:replace(Acc, Regex, Markup, [global, {return, list}]), NewContent end, UpdatedPatternPlus, CheckedShorthandsQuestionMark), CheckedShorthandsAsterisk = [% \s {"\\x{5c}s(?=\\*)", "[ \\\\t\\\\n\\\\r]"}, % \w {"\\x{5c}w(?=\\*)", "[0-9_a-zA-Z]"}, % \h {"\\x{5c}h(?=\\*)", "[\\\\x9\\\\x20]"}, % \v {"\\x{5c}v(?=\\*)", "[\\\\xA-\\\\xD]"}], UpdatedPatternAsterisk = lists:foldl(fun(Elem, Acc) -> Regex = element(1, Elem), Markup = element(2, Elem), NewContent = re:replace(Acc, Regex, Markup, [global, {return, list}]), NewContent end, UpdatedPatternQuestionMark, CheckedShorthandsAsterisk), CheckedShorthands = [% \s {"\\x{5c}s", " \\\\t\\\\n\\\\r"}, % \w {"\\x{5c}w", "0-9_a-zA-Z"}, % \h {"\\x{5c}h", "\\\\x9\\\\x20"}, % \v {"\\x{5c}v", "\\\\xA-\\\\xD"}], UpdatedPattern = lists:foldl(fun(Elem, Acc) -> Regex = element(1, Elem), Markup = element(2, Elem), NewContent = re:replace(Acc, Regex, Markup, [global, {return, list}]), NewContent end, UpdatedPatternAsterisk, CheckedShorthands), UpdatedPattern.