def find(*patterns):
    """Decorate a function to be called for each time a pattern is found in a line.

    :param str patterns: one or more regular expression(s)

    Each argument is a regular expression which will trigger the function::

        @find('hello', 'here')
            # will trigger once on "hello you"
            # will trigger twice on "hello here"
            # will trigger once on "I'm right here!"

    This decorator can be used multiple times to add more rules::

        @find('here')
        @find('hello')
            # will trigger once on "hello you"
            # will trigger twice on "hello here"
            # will trigger once on "I'm right here!"

    If the Sopel instance is in a channel, or sent a ``PRIVMSG``, the function
    will execute for each time a received message matches an expression. Each
    match will also contain the position of the instance it found.

    Inside the regular expression, some special directives can be used.
    ``$nick`` will be replaced with the nick of the bot and ``,`` or ``:``, and
    ``$nickname`` will be replaced with the nick of the bot::

        @find('$nickname')
            # will trigger for each time the bot's nick is in a trigger

    .. versionadded:: 7.1

    .. note::

        The regex rule will match once for each non-overlapping match, from left
        to right, and the function will execute for each of these matches.

        To match only once from anywhere in the line, use the :func:`search`
        decorator instead. To match only once from the start of the line,
        use the :func:`rule` decorator instead.

    """
    def add_attribute(function):
        function._sopel_callable = True
        if not hasattr(function, "find_rules"):
            function.find_rules = []
        for value in patterns:
            if value not in function.find_rules:
                function.find_rules.append(value)
        return function

    return add_attribute