Существует более простой способ использования оболочки (работает на bash 3.2+) для сопоставления с регулярными выражениями:
set isMatch to "0" = (do shell script ¬
"[[ " & quoted form of fileName & " =~ ^[[:digit:]]{10} ]]; printf $?")
Примечание:
- Используется современное выражение для тестирования bash
[[ ... ]]
с оператором сопоставления регулярных выражений, =~
; не цитирование правого операнда (или, по крайней мере, специальных символов регулярных выражений) является обязательным в bash 3.2+, если вы не добавите shopt -s compat31;
- Оператор
do shell script
выполняет тест и возвращает свою команду выхода с помощью дополнительной команды (спасибо, @LauriRanta); "0"
означает успех.
- Обратите внимание, что оператор
=~
не не поддерживает классы символов быстрого доступа, такие как \d
, и утверждения, такие как \b
(верно для OS X 10.9.4 - это вряд ли изменится в любое время в ближайшее время).
- Для нечувствительного к регистру соответствия, перед командной строкой введите
shopt -s nocasematch;
- Для locale-осведомленности , перед командной строкой введите
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
- Вы можете легко сделать сопоставление без учета регистра, позвонив
egrep
с -i
:
- Вы не можете, однако, получить доступ к подматчам через группы захвата; используйте подход
[[ ... =~ ... ]]
, если это необходимо.
Наконец, вот служебные функции , которые объединяют оба подхода (подсветка синтаксиса отключена, но они работают):
# SYNOPIS
# doesMatch(text, regexString) -> Boolean
# DESCRIPTION
# Matches string s against regular expression (string) regex using bash's 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's case sensitivity setting is respected; i.e., matching is case-INsensitive by default, unless inside
# a 'considering case' block.
# - The current user's 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's 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's extended regular expression language and
# *returns the matching string and substrings matching capture groups, if any.*
#
# - AppleScript's 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's 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's 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