30

ファイル名の最初の10文字を解析して、それらがすべて数字であるかどうかを確認する必要があります。これを行うための明白な方法はfileName=〜m / ^ \ d {10} /ですが、applescriptリファレンスにregExyが表示されないため、この検証を行うために他にどのようなオプションが必要か知りたいです。

4

7 に答える 7

25

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の結果はすべて、結果としてスクリプトに返されます。

于 2009-07-17T10:58:35.623 に答える
19

正規表現のマッチングにシェル(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
于 2012-09-06T02:30:48.437 に答える
11

最近、スクリプトで正規表現が必要になり、それを処理するためのスクリプトの追加を見つけたいと思ったので、何が起こっているのかを読みやすくなりました。以下のような構文を使用できる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ビットに更新されたため、予約は不要になりました。必要なことはすべて実行されます。

于 2010-11-08T14:09:30.163 に答える
4

正規表現を折りたたむために呼び出すことができる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
于 2009-06-16T12:27:30.930 に答える
3

文字列の最初の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
于 2014-02-01T07:27:45.993 に答える
2

次のようにして、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のバージョンのリファレンスが見つからないため、使用する前にテストしてください。

于 2019-03-01T22:26:29.420 に答える
1

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
于 2013-07-07T16:37:21.037 に答える