Mysqltcl цикл foreach tcl

Моя проблема заключается в том, что при возврате первого набора отбрасывается $sub1 до того, как его можно будет использовать в сопоставлении строк, поэтому сценарий не продолжается. Я попытался включить остальную часть скрипта в возврат первого набора, и он работает, но... Я получаю несколько сообщений пользователю и каналу для двух других возвратов набора.

В любом случае, чтобы исправить это, чтобы он не отправлял несколько сообщений пользователям и каналу, потому что для каждой подпрограммы в «foreach sub» создается строка для пользователя pm и канала pm, которая может быть где-то от 1 или 2 сообщения до 200 сообщений в зависимости от количества совпадений в базе данных.

bind pubm - * bind_pubm
    proc bind_pubm {nick uhost handle channel text} {
        global SQL; sql:start

        set regexp {^!sub (.*) *$}
        if {[regexp -nocase -- $regexp $text -> subscription]} {
            if {[string match -nocase *HDTV* $subscription] || [string match -nocase *S??E??* $subscription]} {

            set return [mysqlsel $SQL(conn) "select sub from DB_Subs where category='TV'" -list] 
            foreach {sub} $return {     ; # Lists all the subs in the DB for matching.
            regsub -all -- {%} $sub "*" sub1    ; # Replaces % in SQL to * for the String match later.
            }

            if {[string match -nocase $sub1* $subscription]} {  ; # Matches if a sub in the previous list matches the regexp subscription fromthe beginging of proc.
                set return [mysqlsel $SQL(conn) "select user from DB_Subs where sub LIKE '[mysqlescape $sub]%' AND category='TV'" -list]
                    foreach line $return {
                        foreach {user} $line break
                            if {[onchan $user $beta]} {     ; # If the user is on the channel it PM each user.
                                putnow "PRIVMSG $nick : Subscription found matching your request."
                            } else {
                        }
                    }

            set return [mysqlsel $SQL(conn) "select count(DISTINCT user) from DB_Subs where sub LIKE '[mysqlescape $sub]%' AND category='TV'" -flatlist] ; # Counts the users for the Channel message.
                foreach {users} $return break
                    putnow "PRIVMSG $beta :SUBSCRIPTION: $users Users With Subscriptions for $subscription"
            } else {
            }
        } else {
        }
    }
}

Трудно объяснить, чего именно я пытаюсь достичь.

В конце концов, результат, которого я пытаюсь достичь, - это...

  • Установите $subscription из регулярного выражения
  • Список всех подпрограмм в БД
  • Скрыть все % внутри подпрограммы в БД до * для следующего совпадения
  • Попробуйте сопоставить подписку с $subscription
  • Если они совпадают, перейдите к следующему SELECT.
  • Выберите всех «ПОЛЬЗОВАТЕЛЕЙ» из БД, где подпрограмма похожа на %sub%
  • Затем отправьте каждому пользователю сообщение, соответствующее выбранному
  • Возврат последнего набора подсчитывает количество пользователей, которые соответствуют выбору и отправляют сообщение на канал.

После использования решения, которое предложил Донал. Кажется, все работает так, как должно, с одной маленькой проблемой. Часть кода [string match -nocase [get_subscription $SQL(conn)]* $subscription] не сохраняет каждую переменную для проверки. Какая строка появляется первой, она использует вместо этого и останавливается вместо завершения списка, чтобы увидеть, есть ли еще совпадения. Некоторые записи добавляются по-разному, но должны давать одинаковые результаты. например, некоторые записи добавляются как The.TV.Show.S01 или The%TV%Show%S01. Это означает, что он должен соответствовать обоим разделам и получать точное количество и количество пользователей.


person Maphex    schedule 05.03.2013    source источник
comment
Если сложно объяснить, чего вы пытаетесь достичь, разместите несколько разных коротких вопросов, каждый из которых касается ровно одной понятной проблемы. В его нынешнем виде я не уверен, как подойти к вашему вопросу.   -  person kostix    schedule 05.03.2013


Ответы (1)


Вероятно, это сложно, потому что у вас слишком много всего в одной части. Попробуйте разбить код на более мелкие части, которые выполняют четко определенную задачу. Это называется рефакторинг и является важной частью упрощения понимания кода.

Вот несколько рекомендуемых рефакторингов:

proc get_subscription {conn} {
    set return [mysqlsel $conn "select sub from DB_Subs where category='TV'" -list] 
    foreach {sub} $return {
        regsub -all -- {%} $sub "*" sub1
    }
    return $sub1
}

proc notify_subscription_user {conn nick sub beta} {
    set return [mysqlsel $conn "select user from DB_Subs where sub LIKE '[mysqlescape $sub]%' AND category='TV'" -list]
    foreach line $return {
        lassign $line user
        if {[onchan $user $beta]} {
            putnow "PRIVMSG $nick : Subscription found matching your request."
        }
    }
}

proc send_subscription_message {conn sub beta subscription_text} {
    set return [mysqlsel $conn "select count(DISTINCT user) from DB_Subs where sub LIKE '[mysqlescape $sub]%' AND category='TV'" -flatlist]
    lassign $return users
    putnow "PRIVMSG $beta :SUBSCRIPTION: $users Users With Subscriptions for $subscription_text"
}

С их помощью мы можем переписать остальную часть вашего кода, чтобы она была такой (удаление пустых предложений else, разбиение выражений по строкам, объединение вложенных тестов if; все основные вещи):

bind pubm - * bind_pubm
proc bind_pubm {nick uhost handle channel text} {
    global SQL; sql:start

    if {
        [regexp -nocase -- {^!sub (.*) *$} $text -> subscription]
        && ([string match -nocase *HDTV* $subscription]
            || [string match -nocase *S??E??* $subscription])
        && [string match -nocase [get_subscription $SQL(conn)]* $subscription]
    } then {
        notify_subscription_user $SQL(conn) $nick $sub $beta
        send_subscription_message $SQL(conn) $sub $beta $subscription
    }
}

Это решит вашу проблему? Я не знаю, но это должно дать вам гораздо лучшую базу для начала.

person Donal Fellows    schedule 05.03.2013
comment
похоже, что этот процесс будет работать, но у меня проблемы с тем, что $sub не остается установленным, чтобы его можно было использовать в notify_subscription_user и send_subscription_message. - person Maphex; 07.03.2013
comment
другая проблема заключается в том, что подписки сохраняются в различных форматах в БД, некоторые из них могут быть %tv%show или .tv.show, поэтому мне нужно, чтобы они соответствовали обоим, а не только одному - person Maphex; 07.03.2013