Подтвердить что ты не робот

Есть что-то похожее на regEx в applescript, а если нет, то какая альтернатива?

Мне нужно проанализировать первые 10 символов имени файла, чтобы увидеть, все ли они. Очевидный способ сделать это - fileName = ~ m/^\d {10}/, но я не вижу ничего в regExy в ссылке на applescript, так что мне любопытно, какие еще параметры мне нужно сделать для этой проверки.

4b9b3361

Ответ 1

Не отчаивайтесь, так как OSX вы также можете получить доступ к sed и grep через "do shell script". Итак:

set thecommandstring to "echo \"" & filename & "\"|sed \"s/[0-9]\\{10\\}/*good*(&)/\"" as string
set sedResult to do shell script thecommandstring
set isgood to sedResult starts with "*good*"

Мои навыки sed не слишком горячие, поэтому может быть более элегантный способ, чем добавление * хорошего * к любому имени, которое соответствует [0-9] {10}, а затем поиск * хорошего * в начале результат. Но в основном, если имя файла "1234567890dfoo.mov", это запустит команду:

echo "1234567890foo.mov"|sed "s/[0-9]\{10\}/*good*(&)/"

Обратите внимание на экранированные кавычки\"и экранированную обратную косую черту\\в applescript. Если вы избегаете вещей в оболочке, вам нужно избегать экранов. Поэтому для запуска оболочки script, которая имеет обратную косую черту, у вас есть чтобы избежать его для оболочки, как \\, а затем избежать каждой обратной косой черты в applescript, например \\\\. Это может быть довольно трудно прочитать.

Итак, все, что вы можете сделать в командной строке, вы можете сделать, вызвав ее из applescript (woohoo!). Любые результаты на stdout возвращаются в script в результате.

Ответ 2

Существует более простой способ использовать оболочку (работает с bash 3.2+) для соответствия регулярных выражений:

set isMatch to "0" = (do shell script ¬
  "[[ " & quoted form of fileName & " =~ ^[[:digit:]]{10} ]]; printf $?")

Примечание:

  • Использует современное тестовое выражение bash [[ ... ]] с оператором соответствия regex, =~; не ссылаясь на правый операнд (или, по крайней мере, специальные символы регулярных выражений.) является обязательным условием на bash 3.2+, если вы не добавили shopt -s compat31;
  • Оператор do shell script выполняет тест и возвращает свою команду exit с помощью дополнительной команды (спасибо, @LauriRanta); "0" указывает на успех.
  • Обратите внимание, что оператор =~ не поддерживает классы ярлыков символов, такие как \d, и такие утверждения, как \b (true, как OS X 10.9.4 - это вряд ли изменится в ближайшее время).
  • Для соответствия с учетом регистра INSensitive добавьте командную строку с shopt -s nocasematch;
  • Чтобы узнать о локальности, добавьте командную строку с помощью export LANG='" & user locale of (system info) & ".UTF-8';.
  • Если регулярное выражение содержит группы захвата, вы можете получить доступ к захваченным строкам с помощью встроенной переменной массива ${BASH_REMATCH[@]}.
  • Как и в принятом ответе, вы должны будете \ -безать двойные кавычки и обратную косую черту.

Здесь альтернатива, использующая egrep:

set isMatch to "0" = (do shell script ¬
  "egrep -q '^\\d{10}' <<<" & quoted form of filename & "; printf $?")

Хотя это, по-видимому, хуже, оно имеет два преимущества:

  • Вы можете использовать классы ярлыков символов, такие как \d, и такие утверждения, как \b
  • С помощью -i с -i вы можете с легкостью сопоставить регистр-INsensitive, указав -i:
  • Однако вы не можете получить доступ к суб-матчи через группы захвата; используйте подход [[ ... =~ ... ]], если это необходимо.

Наконец, вот служебные функции, которые устанавливают оба подхода (подсветка синтаксиса выключена, но они работают):

# SYNOPIS
#   doesMatch(text, regexString) -> Boolean
# DESCRIPTION
#   Matches string s against regular expression (string) regex using bash extended regular expression language *including* 
#   support for shortcut classes such as `\d`, and assertions such as `\b`, and *returns a Boolean* to indicate if
#   there is a match or not.
#    - AppleScript case sensitivity setting is respected; i.e., matching is case-INsensitive by default, unless inside
#      a 'considering case' block.
#    - The current user locale is respected.
# EXAMPLE
#    my doesMatch("127.0.0.1", "^(\\d{1,3}\\.){3}\\d{1,3}$") # -> true
on doesMatch(s, regex)
    local ignoreCase, extraGrepOption
    set ignoreCase to "a" is "A"
    if ignoreCase then
        set extraGrepOption to "i"
    else
        set extraGrepOption to ""
    end if
    # Note: So that classes such as \w work with different locales, we need to set the shell locale explicitly to the current user's.
    #       Rather than let the shell command fail we return the exit code and test for "0" to avoid having to deal with exception handling in AppleScript.
    tell me to return "0" = (do shell script "export LANG='" & user locale of (system info) & ".UTF-8'; egrep -q" & extraGrepOption & " " & quoted form of regex & " <<< " & quoted form of s & "; printf $?")
end doesMatch

# SYNOPSIS
#   getMatch(text, regexString) -> { overallMatch[, captureGroup1Match ...] } or {}
# DESCRIPTION
#   Matches string s against regular expression (string) regex using bash extended regular expression language and
#   *returns the matching string and substrings matching capture groups, if any.*
#   
#   - AppleScript case sensitivity setting is respected; i.e., matching is case-INsensitive by default, unless this subroutine is called inside
#     a 'considering case' block.
#   - The current user locale is respected.
#   
#   IMPORTANT: 
#   
#   Unlike doesMatch(), this subroutine does NOT support shortcut character classes such as \d.
#   Instead, use one of the following POSIX classes (see `man re_format`):
#       [[:alpha:]] [[:word:]] [[:lower:]] [[:upper:]] [[:ascii:]]
#       [[:alnum:]] [[:digit:]] [[:xdigit:]]
#       [[:blank:]] [[:space:]] [[:punct:]] [[:cntrl:]] 
#       [[:graph:]]  [[:print:]] 
#   
#   Also, `\b`, '\B', '\<', and '\>' are not supported; you can use `[[:<:]]` for '\<' and `[[:>:]]` for `\>`
#   
#   Always returns a *list*:
#    - an empty list, if no match is found
#    - otherwise, the first list element contains the matching string
#       - if regex contains capture groups, additional elements return the strings captured by the capture groups; note that *named* capture groups are NOT supported.
#  EXAMPLE
#       my getMatch("127.0.0.1", "^([[:digit:]]{1,3})\\.([[:digit:]]{1,3})\\.([[:digit:]]{1,3})\\.([[:digit:]]{1,3})$") # -> { "127.0.0.1", "127", "0", "0", "1" }
on getMatch(s, regex)
    local ignoreCase, extraCommand
    set ignoreCase to "a" is "A"
    if ignoreCase then
        set extraCommand to "shopt -s nocasematch; "
    else
        set extraCommand to ""
    end if
    # Note: 
    #  So that classes such as [[:alpha:]] work with different locales, we need to set the shell locale explicitly to the current user's.
    #  Since `quoted form of` encloses its argument in single quotes, we must set compatibility option `shopt -s compat31` for the =~ operator to work.
    #  Rather than let the shell command fail we return '' in case of non-match to avoid having to deal with exception handling in AppleScript.
    tell me to do shell script "export LANG='" & user locale of (system info) & ".UTF-8'; shopt -s compat31; " & extraCommand & "[[ " & quoted form of s & " =~ " & quoted form of regex & " ]] && printf '%s\\n' \"${BASH_REMATCH[@]}\" || printf ''"
    return paragraphs of result
end getMatch

Ответ 3

Мне недавно нужны регулярные выражения в script, и я хотел бы найти дополнение к скрипту для его обработки, поэтому было бы легче прочитать, что происходит. Я нашел Satimage.osax, который позволяет использовать синтаксис, как показано ниже:

find text "n(.*)" in "to be or not to be" with regexp

Единственным недостатком является то, что (по состоянию на 11/08/2010) это 32-битное дополнение, поэтому он выдает ошибки при вызове из 64-битного процесса. Это немного меня в Mail правило для Snow Leopard, поскольку мне пришлось запускать Mail в 32-битном режиме. Вызывается из автономного script, хотя у меня нет никаких оговорок - это действительно здорово и позволяет вам выбрать любой синтаксис регулярных выражений, который вы хотите, и используйте обратные ссылки.

Обновление 5/28/2011

Благодаря комментарию Mitchell Model ниже, указав, что они обновили его до 64 бит, поэтому больше никаких оговорок - он делает все, что мне нужно.

Ответ 4

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

set filename to "1234567890abcdefghijkl"

return isPrefixGood(filename)

on isPrefixGood(filename) --returns boolean
    set legalCharacters to {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}

    set thePrefix to (characters 1 thru 10) of filename as text

    set badPrefix to false

    repeat with thisChr from 1 to (get count of characters in thePrefix)
        set theChr to character thisChr of thePrefix
        if theChr is not in legalCharacters then
            set badPrefix to true
        end if
    end repeat

    if badPrefix is true then
        return "bad prefix"
    end if

    return "good prefix"
end isPrefixGood

Ответ 5

Здесь другой способ проверить, являются ли первые десять символов любой строки цифрами.

    on checkFilename(thisName)
        set {n, isOk} to {length of fileName, true}
        try
            repeat with i from 1 to 10
                set isOk to (isOk and ((character i of thisName) is in "0123456789"))
            end repeat
            return isOk
        on error
            return false
        end try
    end checkFilename

Ответ 6

У меня есть альтернатива, пока я не реализовал класс символов для алгоритма Thompson NFA. Я сделал голые кости работы в AppleScript. Если кто-то заинтересован в поиске синтаксического анализа основного элемента с Applescript, тогда код отправляется в CodeExchange в MacScript, пожалуйста, посмотрите!

Вот решение для выяснения, есть ли десять первых символов текста/строки:

 set mstr to "1234567889Abcdefg"
set isnum to prefixIsOnlyDigits for mstr
to prefixIsOnlyDigits for aText
    set aProbe to text 1 thru 10 of aText
    set isnum to false
    if not ((offset of "," in aProbe) > 0 or (offset of "." in aProbe) > 0 or (offset of "-" in aProbe) > 0) then
        try
            set aNumber to aProbe as number
            set isnum to true
        end try
    end if
    return isnum
end prefixIsOnlyDigits