ファイル名の最初の10文字を解析して、それらがすべて数字であるかどうかを確認する必要があります。これを行うための明白な方法はfileName=〜m / ^ \ d {10} /ですが、applescriptリファレンスにregExyが表示されないため、この検証を行うために他にどのようなオプションが必要か知りたいです。
7 に答える
OSXは「doshellscript」を介してsedとgrepにアクセスすることもできるので、絶望しないでください。それで:
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}に一致する名前に*good *を追加し、結果の先頭で*good*を探すよりもエレガントな方法があるかもしれません。ただし、基本的に、ファイル名が「1234567890dfoo.mov」の場合、次のコマンドが実行されます。
echo "1234567890foo.mov"|sed "s/[0-9]\{10\}/*good*(&)/"
AppleScriptのエスケープされた引用符\"とエスケープされたバックスラッシュ\\に注意してください。シェルでエスケープする場合は、エスケープをエスケープする必要があります。したがって、バックスラッシュを含むシェルスクリプトを実行するには、エスケープする必要があります。 \\のようなシェルを作成し、\\\\のようなAppleScriptの各バックスラッシュをエスケープします。これはかなり読みにくくなる可能性があります。
したがって、コマンドラインで実行できることはすべて、applescriptから呼び出すことで実行できます(woohoo!)。stdoutの結果はすべて、結果としてスクリプトに返されます。
正規表現のマッチングにシェル(bash 3.2以降で動作)を利用する簡単な方法があります。
set isMatch to "0" = (do shell script ¬
"[[ " & quoted form of fileName & " =~ ^[[:digit:]]{10} ]]; printf $?")
ノート:
[[ ... ]]
正規表現マッチング演算子を使用した最新のbashテスト式を利用し=~
ます。右のオペランド(または少なくとも特別な正規表現文字)を引用符で囲まないことは、先頭に追加しない限り、bash3.2以降では必須です。shopt -s compat31;
- ステートメントは
do shell script
テストを実行し、追加のコマンドを介してその終了コマンドを返します(ありがとう、@ LauriRanta)。"0"
成功を示します。 =~
オペレーターは、などのショートカット文字クラスやなどのアサーションをサポートしていないことに注意してください(OS X 10.9.4の時点ではtrue-これはすぐに変更される可能性は低いです)。\d
\b
- 大文字と小文字を区別しないマッチングの場合は、コマンド文字列の前に
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 $?")
これはおそらくパフォーマンスが低下しますが、2つの利点があります。
- などのショートカット文字クラスとなどの
\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
最近、スクリプトで正規表現が必要になり、それを処理するためのスクリプトの追加を見つけたいと思ったので、何が起こっているのかを読みやすくなりました。以下のような構文を使用できるSatimage.osaxを見つけました。
find text "n(.*)" in "to be or not to be" with regexp
唯一の欠点は、(2010年11月8日現在)32ビットの追加であるため、64ビットプロセスから呼び出されたときにエラーがスローされることです。私は32ビットモードでメールを実行しなければならなかったので、これはSnowLeopardのメールルールで私を噛みました。ただし、スタンドアロンスクリプトから呼び出されますが、予約はありません。これは非常に優れており、必要な正規表現構文を選択して、後方参照を使用できます。
2011年5月28日更新
以下のミッチェルモデルのコメントのおかげで、64ビットに更新されたため、予約は不要になりました。必要なことはすべて実行されます。
正規表現を折りたたむために呼び出すことができるApplescriptAdditionまたはシェルスクリプトがあると確信していますが、単純なものへの依存は避けています。私はいつもこのスタイルのパターンを使用しています...
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
文字列の最初の10文字が数字かどうかを確認する別の方法があります。
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
次のようにして、AppleScript(High Sierra上)からJavaScriptを直接呼び出すことができました。
# Returns a list of strings from _subject that match _regex
# _regex in the format of /<value>/<flags>
on match(_subject, _regex)
set _js to "(new String(`" & _subject & "`)).match(" & _regex & ")"
set _result to run script _js in "JavaScript"
if _result is null or _result is missing value then
return {}
end if
return _result
end match
match("file-name.applescript", "/^\\d+/g") #=> {}
match("1234_file.js", "/^\\d+/g") #=> {"1234"}
match("5-for-fighting.mp4", "/^\\d+/g") #=> {"5"}
ほとんどのJavaScript文字列メソッドは期待どおりに機能しているようです。JavaScript for macOS Automationが互換性のあるECMAScriptのバージョンのリファレンスが見つからないため、使用する前にテストしてください。
Thompson NFAアルゴリズムの文字クラスを実装するまでは、AppleScriptで必要最低限の作業を行うという代替手段があります。非常に基本的な正規表現をApplescriptで解析することに興味がある人は、コードがMacScriptersのCodeExchangeに投稿されています。ぜひご覧ください。
テキスト/文字列の最初の10文字かどうかを判断するための解決策は次のとおりです。
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