AppleScript名:バージョン番号文字列からメジャーバージョンを取り出し数値として返す v4 |
use AppleScript version "2.4" use scripting additions use framework "Foundation" set a to "10.0.1" set b to retMajorVersionNumber(a) of me –> 10 set a to "9.10" set b to retMajorVersionNumber(a) of me –> 9 –バージョン番号文字列からメジャーバージョンを取り出し数値として返す on retMajorVersionNumber(a) set aStr to current application’s NSString’s stringWithString:a –> "10.0.1" (NSString) set aRes to (aStr’s componentsSeparatedByString:".") –> {"10","0","1"} (NSArray) set bRes to aRes’s firstObject() –> "10" (NSString) set cRes to bRes’s integerValue() –> 10 return cRes as integer end retMajorVersionNumber |
タグ: 10.12savvy
ASOCでbase64エンコード、デコード v3
AppleScript名:ASOCでbase64エンコード、デコード v3 |
— Created 2015-07-27 by Takaaki Naganoya — Updated 2015-07-28 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" set aStr to "ぴよまるソフトウェアPiyomaru Software" set theNSString to current application’s NSString’s stringWithString:aStr set theNSData to theNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set bStr to base64StringFromFileString(aStr) of me return bStr –> "44G044KI44G+44KL44K944OV44OI44Km44Kn44KiUGl5b21hcnUgU29mdHdhcmU=" set aFilePath to POSIX path of (choose file) base64StringFromFileAtPath(aFilePath) of me –Base 64 Decode on detaFromBase64String(aStr) set dataFrom64 to current application’s NSData’s alloc()’s initWithBase64EncodedString:aStr options:(current application’s NSDataBase64DecodingIgnoreUnknownCharacters) set aStr to current application’s NSString’s alloc()’s initWithData:dataFrom64 encoding:(current application’s NSUTF8StringEncoding) return aStr as text –stringではなくtext end detaFromBase64String –Base64 Encode on base64StringFromFileAtPath(aFilePath) set aDataFromFile to current application’s NSData’s dataWithContentsOfFile:aFilePath set aBase64EncStr to aDataFromFile’s base64EncodedStringWithOptions:(current application’s NSDataBase64Encoding64CharacterLineLength) return aBase64EncStr as text end base64StringFromFileAtPath –Base64 Encode on base64StringFromFileString(aString) set bString to current application’s NSString’s stringWithString:aString set aData to bString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set aBase64EncStr to aData’s base64EncodedStringWithOptions:(current application’s NSDataBase64Encoding64CharacterLineLength) return aBase64EncStr as text end base64StringFromFileString |
テキストによるプログレスインジケータ作成 v2
AppleScript名:テキストによるプログレスインジケータ作成 v2 |
set aList to {50, 24} –max-num, cur-num set cList to {".", "o"} set aRes to retProgressChar(aList, cList) of me –> "ooooo….." on retProgressChar(aList, cList) set barCharLen to 10 set allNum to item 1 of aList set doneNum to item 2 of aList if doneNum > allNum then return "" set oneStep to 100 / allNum set curStep to doneNum * oneStep set stringBar to (curStep / barCharLen) set stringBar2 to round stringBar rounding as taught in school –未処理アイテム数 set notYet to barCharLen – stringBar2 set notYetChar to contents of item 1 of cList set doneChar to contents of item 2 of cList set notYetText to makeCharRep(notYet, notYetChar) of me set doneText to makeCharRep(stringBar2, doneChar) of me set aText to doneText & notYetText return aText end retProgressChar –指定文字を指定回数連結したテキストを返す on makeCharRep(aNum, aChar) set aText to "" repeat aNum times set aText to aText & aChar end repeat return aText end makeCharRep |
同じ文字を指定回数繰り返して出力
AppleScript名:同じ文字を指定回数繰り返して出力 |
retSeriesOfSameChar("絆", 30) on retSeriesOfSameChar(aChar, aCount) set outStr to "" repeat with i from 1 to aCount set outStr to outStr & aChar end repeat end retSeriesOfSameChar |
Unicodeの文字をNormalizeする
UTF-8の文字列を、NFD/NFKD/NFC/NFKCの各正規化形式で正規化し、チェックのためのhexdumpするAppleScriptです。
NSStringの状態でNFD/NFKD/NFC/NFKCの各正規化形式で正規化して、そのままAppleScriptのstringに「as string」でcastしても、その正規化の状態は維持されます。
外部から他のOS上で作成したデータを取り込んで扱う場合に、文字列であっても正規化形式が異なるパターンがあります。実際に、PDFから文字列を取り出して、そのまま処理したところ同じ文字列なのに照合できないというケースがありました。その場合に、本Scriptで利用している正規化処理で明示的にいったん処理してからAppleScriptのstringにcastしたところ問題なく扱えました。
問題があった場合には、まずHexdumpして文字列の内容がどのようになっているかをチェックしています。目に見える文字が同じなのにプログラム側からは同じデータとして判定できないという例は、たまにある話なので。
AppleScript名:Unicodeの文字をNormalizeする |
— Created 2015-09-30 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" –Reference: –http://akisute.com/2010/05/utf-8-normalize.html –http://nomenclator.la.coocan.jp/unicode/normalization.htm set a to "がぎぐげご" set aStr to current application’s NSString’s stringWithString:a log hexDumpString(aStr) –> {"E3", "81", "8C", "E3", "81", "8E", "E3", "81", "90", "E3", "81", "92", "E3", "81", "94"} –NFD set aNFD to aStr’s decomposedStringWithCanonicalMapping() –> (NSString) "がぎぐげご" log hexDumpString(aNFD) –> {"E3", "81", "8B", "E3", "82", "99", "E3", "81", "8D", "E3", "82", "99", "E3", "81", "8F", "E3", "82", "99", "E3", "81", "91", "E3", "82", "99", "E3", "81", "93", "E3", "82", "99"} –NFKD set aNFKD to aStr’s decomposedStringWithCompatibilityMapping() –> (NSString) "がぎぐげご" log hexDumpString(aNFKD) –> {"E3", "81", "8B", "E3", "82", "99", "E3", "81", "8D", "E3", "82", "99", "E3", "81", "8F", "E3", "82", "99", "E3", "81", "91", "E3", "82", "99", "E3", "81", "93", "E3", "82", "99"} –NFC set aNFC to aStr’s precomposedStringWithCanonicalMapping() –> (NSString) "がぎぐげご" log hexDumpString(aNFC) –> {"E3", "81", "8C", "E3", "81", "8E", "E3", "81", "90", "E3", "81", "92", "E3", "81", "94"} –NFKC set aNFKC to aStr’s precomposedStringWithCompatibilityMapping() –> (NSString) "がぎぐげご" log hexDumpString(aNFKC) –> {"E3", "81", "8C", "E3", "81", "8E", "E3", "81", "90", "E3", "81", "92", "E3", "81", "94"} –NSStringをhexdumpする on hexDumpString(theNSString) set theNSData to theNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set theString to (theNSData’s |description|()’s uppercaseString()) –Remove "<" ">" characters in head and tail set tLength to (theString’s |length|()) – 2 set aRange to current application’s NSMakeRange(1, tLength) set theString2 to theString’s substringWithRange:aRange –Replace Space Characters set aString to current application’s NSString’s stringWithString:theString2 set bString to aString’s stringByReplacingOccurrencesOfString:" " withString:"" set aResList to splitString(bString, 2) –> {"E3", "81", "82", "E3", "81", "84", "E3", "81", "86", "E3", "81", "88", "E3", "81", "8A"} return aResList end hexDumpString –Split NSString in specified aNum characters on splitString(aText, aNum) set aStr to current application’s NSString’s stringWithString:aText if aStr’s |length|() ≤ aNum then return aText set anArray to current application’s NSMutableArray’s new() set mStr to current application’s NSMutableString’s stringWithString:aStr set aRange to current application’s NSMakeRange(0, aNum) repeat while (mStr’s |length|()) > 0 if (mStr’s |length|()) < aNum then anArray’s addObject:(current application’s NSString’s stringWithString:mStr) mStr’s deleteCharactersInRange:(current application’s NSMakeRange(0, mStr’s |length|())) else anArray’s addObject:(mStr’s substringWithRange:aRange) mStr’s deleteCharactersInRange:aRange end if end repeat return (current application’s NSArray’s arrayWithArray:anArray) as list end splitString |
デコードしたQRコードのメールデータの各フィールドを取り出す v2.2
AppleScript名:デコードしたQRコードのメールデータの各フィールドを取り出す v2.2 |
— Created 2016-12-12 by Shane Stanley — Modified 2016-12-14 by edama2 — Modified 2017-01-12 by Takaaki Naganoya use AppleScript version "2.4" use scripting additions use framework "Foundation" set aStr to "こんにちは、ぴよまるです MATMSG:TO:hiyoko@piyocast.com;SUB:たいとる;BODY:ほんぶん;; Takaaki Naganoya iPhoneから送信" set aDict to (parseStrByParamlabelAndTail(aStr, "MATMSG:", ":", ";") of me) set eMailAddrs to (aDict’s valueForKey:"TO") as string–> "hiyoko@piyocast.com" set aSubject to (aDict’s valueForKey:"SUB") as string –> "たいとる" set aBody to (aDict’s valueForKey:"BODY") as string –> "ほんぶん" on parseStrByParamlabelAndTail(aParamStr, aDataHeader, aParamLabel, aParamTail) set theScanner to current application’s NSScanner’s scannerWithString:aParamStr set aDict to current application’s NSMutableDictionary’s |dictionary|() —Skip over the data header set {theResult, theKey} to theScanner’s scanUpToString:aDataHeader intoString:(reference) if theResult as boolean = false then return false –Error: Data header is not present theScanner’s scanString:aDataHeader intoString:(missing value) repeat until (theScanner’s isAtEnd as boolean) — terminate check, return the result (aDict) to caller set {theResult, theKey} to theScanner’s scanUpToString:aParamLabel intoString:(reference) — skip over separator theScanner’s scanString:aParamLabel intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:aParamTail intoString:(reference) if theValue is missing value then set theValue to "" — skip over separator theScanner’s scanString:aParamTail intoString:(missing value) aDict’s setObject:theValue forKey:theKey end repeat return aDict end parseStrByParamlabelAndTail |
指定言語のスペルチェックを行い、候補文を返す
AppleScript名:指定言語のスペルチェックを行い、候補文を返す |
— Created 2015-12-18 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" set aText to "This is a penz." set spRes to spellCheckingInSpecifiedLanguage(aText, "English") of me –> {missed:"penz", suggestionList:{"This Is A Pens", "This Is A Pend", "This Is A Penh", "This Is A Penn", "This Is A Pent", "This is a pen"}} set aText to "Applele" set spRes to spellCheckingInSpecifiedLanguage(aText, "English") of me –> {missed:"Applele", suggestionList:{"Apple", "Apples", "Appeal", "Appalled", "Appellate"}} set aText to "Applele" set spRes to spellCheckingInSpecifiedLanguage(aText, "French") of me –> {missed:"Applele", suggestionList:{"Appelle", "Appelée", "Appelles"}} set spRes to spellCheckingInSpecifiedLanguage(aText, "fr") of me –> {missed:"Applele", suggestionList:{"Appelle", "Appelée", "Appelles"}} on spellCheckingInSpecifiedLanguage(aText, aLang) set aStr to current application’s NSString’s stringWithString:aText set aChecker to current application’s NSSpellChecker’s sharedSpellChecker() aChecker’s setLanguage:aLang set aMisspelledRange to aChecker’s checkSpellingOfString:aStr startingAt:0 if aMisspelledRange’s |length|() = 0 then return missing value –Get Misspelled String set aMisString to (aStr’s substringWithRange:aMisspelledRange) as text –Get Suggestion set aSugList to (aChecker’s guessesForWord:aStr) as list –> {"This Is A Pens", "This Is A Pend", "This Is A Penh", "This Is A Penn", "This Is A Pent", "This is a pen"} return {missed:aMisString, suggestionList:aSugList} end spellCheckingInSpecifiedLanguage |
英文のスペルチェックを行い、候補文を返す
AppleScript名:英文のスペルチェックを行い、候補文を返す |
— Created 2015-12-18 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" set aText to "This is a penz." set spRes to spellChecking(aText) of me –> {missed:"penz", suggestionList:{"This Is A Pens", "This Is A Pend", "This Is A Penh", "This Is A Penn", "This Is A Pent", "This is a pen"}} set aText to "AppleScript" set spRes to spellChecking(aText) of me –> missing value set aText to "Applele" set spRes to spellChecking(aText) of me –> {missed:"Applele", suggestionList:{"Apple", "Apples", "Appeal", "Appalled", "Appellate"}} on spellChecking(aText) set aStr to current application’s NSString’s stringWithString:aText set aChecker to current application’s NSSpellChecker’s sharedSpellChecker() set aMisspelledRange to aChecker’s checkSpellingOfString:aStr startingAt:0 if aMisspelledRange’s |length|() = 0 then return missing value –Get Misspelled String set aMisString to (aStr’s substringWithRange:aMisspelledRange) as text –Get Suggestion set aSugList to (aChecker’s guessesForWord:aStr) as list –> {"This Is A Pens", "This Is A Pend", "This Is A Penh", "This Is A Penn", "This Is A Pent", "This is a pen"} return {missed:aMisString, suggestionList:aSugList} end spellChecking |
NSSpellCheckerでスペルチェック可能な言語の一覧リストを取得_v2
AppleScript名:NSSpellCheckerでスペルチェック可能な言語の一覧リストを取得_v2 |
— Created 2015-12-18 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aChecker to current application’s NSSpellChecker’s sharedSpellChecker() set langList to (aChecker’s availableLanguages()) as list –> {"en", "en_GB", "en_AU", "en_CA", "en_IN", "en_SG", "fr", "da", "de", "es", "it", "nl", "nb", "pl", "pt_BR", "pt_PT", "fi", "sv", "tr", "ru", "ko"} set langNameList to {} repeat with i in langList set j to contents of i –set aLocale to (current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:j) set aLocale to current application’s NSLocale’s currentLocale() set aLocName to (aLocale’s displayNameForKey:(current application’s NSLocaleIdentifier) value:j) set cntLocs to (aLocale’s displayNameForKey:(current application’s NSLocaleLanguageCode) value:j) set cntName to getCountryNameFromLanguageCode(j) of me set the end of langNameList to {aLocName as string, cntName as text, cntLocs as text} end repeat return langNameList –> {{"英語", "アメリカ合衆国", "英語"}, {"英語 (イギリス)", "イギリス", "英語"}, {"英語 (オーストラリア)", "オーストラリア", "英語"}, {"英語 (カナダ)", "カナダ", "英語"}, {"英語 (インド)", "インド", "英語"}, {"英語 (シンガポール)", "シンガポール", "英語"}, {"フランス語", "フランス", "フランス語"}, {"デンマーク語", "デンマーク", "デンマーク語"}, {"ドイツ語", "ドイツ", "ドイツ語"}, {"スペイン語", "スペイン", "スペイン語"}, {"イタリア語", "イタリア", "イタリア語"}, {"オランダ語", "オランダ", "オランダ語"}, {"ノルウェー語(ブークモール)", "ノルウェー", "ノルウェー語(ブークモール)"}, {"ポーランド語", "ポーランド", "ポーランド語"}, {"ポルトガル語 (ブラジル)", "ブラジル", "ポルトガル語"}, {"ポルトガル語 (ポルトガル)", "ポルトガル", "ポルトガル語"}, {"フィンランド語", "フィンランド", "フィンランド語"}, {"スウェーデン語", "スウェーデン", "スウェーデン語"}, {"トルコ語", "トルコ", "トルコ語"}, {"ロシア語", "ロシア", "ロシア語"}, {"韓国語", "大韓民国", "韓国語"}} on getCountryNameFromLanguageCode(aCode) –http://www.benricho.org/translate/countrycode.html if aCode is equal to "en" then set aCode to aCode & "_US" else if aCode is equal to "fr" then set aCode to aCode & "_FR" else if aCode is equal to "da" then set aCode to aCode & "_DK" else if aCode is equal to "de" then set aCode to aCode & "_DE" else if aCode is equal to "es" then set aCode to aCode & "_ES" else if aCode is equal to "it" then set aCode to aCode & "_IT" else if aCode is equal to "nl" then set aCode to aCode & "_NL" else if aCode is equal to "nb" then set aCode to aCode & "_NO" else if aCode is equal to "pl" then set aCode to aCode & "_PL" else if aCode is equal to "fi" then set aCode to aCode & "_FI" else if aCode is equal to "sv" then set aCode to aCode & "_SE" else if aCode is equal to "tr" then set aCode to aCode & "_TR" else if aCode is equal to "ru" then set aCode to aCode & "_RU" else if aCode is equal to "ko" then set aCode to aCode & "_KR" else if aCode is equal to "ja" then set aCode to aCode & "_JP" end if set aLocale to current application’s NSLocale’s currentLocale() set aLoc to (current application’s NSLocale’s alloc()’s initWithLocaleIdentifier:aCode) set aLocCode to aLoc’s objectForKey:(current application’s NSLocaleCountryCode) set aLocName to aLocale’s displayNameForKey:(current application’s NSLocaleCountryCode) value:aLocCode return aLocName end getCountryNameFromLanguageCode |
articlereducerのじっけん(Japanese)
AppleScript名:articlereducerのじっけん(Japanese) |
— Created 2017-06-28 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "articlereducer" –https://github.com/EthanArbuckle/articlereducer set aStr to "ライター/編集者仲間である友人と雑談していたところ、自然言語処理がいろいろ使えそうなシーンが見えてきました。彼によると、Twitter上で過去記事の紹介ツイートを行いたいが、何も関係ないところに唐突に記事紹介のツイートを投げても不自然だし、興味を持たれにくいので、時事ネタと関連する記事を紹介する仕組みを作れないだろうか、という話になりました。 そこで、比較的鮮度および注目度が高いと思われる「ニュース記事」から固有名詞だけを抽出し、その固有名詞にどのぐらい世間的な注目が集まっているかを判定できると、そのキーワードに関連する過去記事をツイートしやすくなるかもしれないと考えました。 apitoreのREST APIには、ニュースフィードを提供するもの、形態素解析を行うもの、Twitter検索を行うものなどがあり、これらを組み合わせるとできそうな感じがしてきました。 → Playing with rest api 実際に試してみたところ、ニュースフィードからニュース記事本文を抽出するのは(RSS Feedに本文の冒頭部分が含まれていないケースもあるので、結局記事のサイトを見に行って本文を抽出する必要がある)けっこう大変で、タイトル(題名)のみ処理することに。 次に、タイトルの文章を形態素解析して、「固有名詞」だけを抽出してみました。これは別に難しくもなんともありません。さらに、入り組んだrecordから目的のデータを取り出すのは、AppleScriptでもCocoaの機能を使えば造作もありません。NSDictionaryからvalueForKeyPath:でオブジェクトパスを記述して抽出すれば、データ取り出しのために長々とループ処理で記述する必要はありません。 次の段階は、その時点における「注目度」の計算です。仮にTwitter全体を1つの「世間」とみなし、Twitter上で拡散されていたりお気に入りに入れられる回数の高い単語は、比較的「注目度」が高いものだろうという仮説を立てました。 → キーワードの言語ごとのTwitter発言内容集計 そこで、ニュースのタイトルから抽出した固有名詞をTwitterで検索し、それぞれの固有名詞がTweet上でどの程度リツイートされたか、お気に入りに入れられたかを計算してみました。これについては、コストの問題からREST APIではなくローカルのmacOS上で動作するAppleScript用Twitterクライアント「TwitterScripter」を呼び出すことにしました。apitore上の各種REST APIは無料で試用できますが、呼び出し回数が増えれば料金がかかるため、その部分を節約することが目的です。TwitterScripterを使用することによるデメリットは、それ自体が並列処理に対応していないこと。Mac上で(AppleScriptによる)並列処理を行ってTwitter検索を行う場合には、直接Twitterの(割と整理されていない)APIを直接呼び出すか、apitore上のREST APIを呼び出すしかなさそうです。 → AS.Parallel 指定のキーワード(固有名詞)を含むツイートをTwitter上で検索し、それぞれがどの程度リツイートされたか、お気に入りに入れられたかを実際に数値化。その数値をもとにキーワードのランキングを計算することができました。 一応、「活性度の高い」≒「注目度の高い」キーワードを計算できたわけです。ここまでのプログラムはすでに実稼働状態にあり、「こんな(へんな)単語が注目されてるのかー!」という未知の単語のピックアップに成功しています。 ただし、これでは目的を50%しか達成できていません。 この「注目度の高いキーワード」と「過去記事」の間をブリッジする必要があるからです。もう少しわかりやすくいえば、「カール」という本日注目度急上昇中のキーワードがありますが、この「カール」という固有名詞で過去記事を検索したところで、まったく異なる単語の一部がたまたま偶然ひっかかってヒットする程度で、過去記事が超絶的にヒットしにくいことが予想されます(グスタフ・カールとかザンスカール帝国とかカール自走臼砲とかパリダカールラリーとか)。 この「カール」を「スナック菓子」という上位概念に変換し、さらにスナック菓子に所属する単語を取得して、それらの単語で検索できるとよいでしょう(菓子、和菓子など)。このあたりは個人的に「スター・クエリー」と昔から呼んでいるもので、与えられたキーワードから類似・関連するキーワードを複数生成して検索することで、ヒットする確率を高める仕組みです。GoogleやYouTubeでもおそらく類似の機構が検索エンジンに実装されており、入力した単語以外でもヒットするようになっているようです(とくにYouTube)。 apitoreでも日本語Word.netのデータを利用して類義語や上位概念の言葉を計算できるようになっていますが、日本語の基本的な語句に特化しており、実際に試してみたところ「カール」「ガンダム」といった商品名などから類義語や上位概念を求める用途に向いていないことがわかりました。これらの計算を行うためには、Wikipediaのデータからカテゴリを取得できれば、やりやすくなるものと思われます。" set aCond to current application’s EACondensor’s alloc()’s initWithText:aStraCond’s setAverageThreshold:(1.0 as real) set shortStr to (aCond’s condensedString()) as string –> "ライター/編集者仲間である友人と雑談していたところ、自然言語処理がいろいろ使えそうなシーンが見えてきました。彼によると、Twitter上で過去記事の紹介ツイートを行いたいが、何も関係ないところに唐突に記事紹介のツイートを投げても不自然だし、興味を持たれにくいので、時事ネタと関連する記事を紹介する仕組みを作れないだろうか、という話になりました。そこで、比較的鮮度および注目度が高いと思われる「ニュース記事」から固有名詞だけを抽出し、その固有名詞にどのぐらい世間的な注目が集まっているかを判定できると、そのキーワードに関連する過去記事をツイートしやすくなるかもしれないと考えました。apitoreのREST APIには、ニュースフィードを提供するもの、形態素解析を行うもの、Twitter検索を行うものなどがあり、これらを組み合わせるとできそうな感じがしてきました。→ Playing with rest api実際に試してみたところ、ニュースフィードからニュース記事本文を抽出するのは(RSS Feedに本文の冒頭部分が含まれていないケースもあるので、結局記事のサイトを見に行って本文を抽出する必要がある)けっこう大変で、タイトル(題名)のみ処理することに。次に、タイトルの文章を形態素解析して、「固有名詞」だけを抽出してみました。これは別に難しくもなんともありません。さらに、入り組んだrecordから目的のデータを取り出すのは、AppleScriptでもCocoaの機能を使えば造作もありません。NSDictionaryからvalueForKeyPath:でオブジェクトパスを記述して抽出すれば、データ取り出しのために長々とループ処理で記述する必要はありません。次の段階は、その時点における「注目度」の計算です。仮にTwitter全体を1つの「世間」とみなし、Twitter上で拡散されていたりお気に入りに入れられる回数の高い単語は、比較的「注目度」が高いものだろうという仮説を立てました。→ キーワードの言語ごとのTwitter発言内容集計そこで、ニュースのタイトルから抽出した固有名詞をTwitterで検索し、それぞれの固有名詞がTweet上でどの程度リツイートされたか、お気に入りに入れられたかを計算してみました。これについては、コストの問題からREST APIではなくローカルのmacOS上で動作するAppleScript用Twitterクライアント「TwitterScripter」を呼び出すことにしました。apitore上の各種REST APIは無料で試用できますが、呼び出し回数が増えれば料金がかかるため、その部分を節約することが目的です。TwitterScripterを使用することによるデメリットは、それ自体が並列処理に対応していないこと。Mac上で(AppleScriptによる)並列処理を行ってTwitter検索を行う場合には、直接Twitterの(割と整理されていない)APIを直接呼び出すか、apitore上のREST APIを呼び出すしかなさそうです。→ AS. " |
要約(Summarize)のじっけん
AppleScript名:要約(Summarize)のじっけん |
— Created 2016-11-15 by Takaaki Naganoya — 2016 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set piyoText to "githubで公開されているオープンソースのフレームワーク「HTTPServerKit」(By David Thorpe氏)を呼び出して、簡易http(Web)サーバー機能を起動するAppleScriptです。 AppleScriptとWeb CGIのつながりは割と昔(Classic Mac OS 7の時代)からあったのですが、Macの1U Server機(Xserve)が廃止になり、Mac OS X ServerがOSからツール集的な位置付けに後退。macOS 10.8ですでにMac OS Xの標準機能としての「Web共有」はGUI画面上から消えました。 MacをWebサーバーにするような使い方は、作っている方も使う方もあまり重視しなくなってきたともいえますが(WebObjectsで稼働し続けているiTunes Storeをのぞく)、局地的かつ限定された用途において、他のOSプラットフォームからMac内の機能を共有するようなケースでは、使えてほしいものです。 そうしたニーズを受けてか、github上で探してみるといろいろ「簡易Webサーバー」的なプロジェクトを見ることができます。本、HTTPServerKitもそのうちのひとつです。 スクリプトエディタ上で呼び出して処理が終わったら終了、というようなバッチ処理的なありがちなAppleScriptの運用スタイルとは相入れませんが、常駐アプレットとして運用する場合やXcode上で作成するCocoa-AppleScriptアプレットでは利用できるはずです。 本サンプルでは、ホームディレクトリ下の「サイト」(~/Sites)フォルダをDoc Rootに、8081をポート番号に指定してWebサーバー(thttpd)を起動し、60秒間httpのリクエストを受け付け、Webサーバーを終了させます。 すでに、「サイト」フォルダが存在していること、同フォルダ内に「index.html」ファイルが存在していることを前提にしているため、OS X 10.12をクリーンインストールした環境ではファイルが存在せずにうまく動かない可能性もあります(Sitesフォルダが存在しない場合には自動作成しています)。 注意すべき点は、起動したhttpサーバー(thttpd)は、明示的に終了(stop())を行わないと、どんどんプロセスが追加で起動されてしまい、AppleScript側に正しくログなどを返さないようになってしまうことです。毎回、こまめにstop()を呼び出しましょう。 実際にこうして呼び出して評価してみると、やや機能が素朴すぎるきらいがあり、このHTTPServerKitが決定版になるかと言われると、ちょっとつらい気もします。http経由でファイル転送なども行いたいですし、何らかのプログラム呼び出しインタフェースは欲しい気がします。 ただ、ラジオ番組を録音してmp3に変換し、LAN上でiPhoneなどにPodcastとして配信するような用途(ありがち)だと、このぐらいの機能レベルのソフトウェアが合っているようにも見えます。 また、AppleScriptでOAuth2.0の認証を行うような場合に、認証後に表示させるredirect URIについて、「http://localhost」などと指定させたりしますが、もっと気の利いた表示を行うために本Scriptを併用して指定のHTMLを強制表示させるような用途にも使えそうです(redirect_uri:”http://localhost:8081″ のように)。 LAN上の他のOSのマシンからMacを操作させることを目的として、簡易httpサーバーソフトウェアをいろいろと物色しています。ポート番号を指定する機能がないと、デフォルトで起動しているhttpdとコンフリクトを起こしてしまうので、ポート番号指定機能は必須の条件です。 なお、HTTPServerKit.frameworkのビルドは、githubからプロジェクトをダウンロードしてXcodeでいろいろ試しても、ビルドディレクトリを変更したり、日本語を含まないパス上にプロジェクトを移動させたりしても、エラー終了してしまいました(出来がよくない?)。 実際に試す場合には、ビルドされたバイナリをダウンロードするほかないと思われます。AppleScriptの実行前にフレームワークのバイナリを~/Library/Frameworksに入れておいてください。" set bText to summarizeInSpecifiedChars(piyoText, 400) on summarizeInSpecifiedChars(piyoText as string, aLimit as integer)if length of piyoText ≥ aLimit then set pLen to paragraphs of piyoText repeat with i from 1 to (length of pLen) by 1 set bCon to (summarize piyoText in i) as string set p2Len to length of bCon if p2Len ≥ aLimit then if i = 1 then set i to 1 else set i to i – 1 end if exit repeat end if end repeat return (summarize piyoText in i) else return piyoText end if end summarizeInSpecifiedChars |
offset ofの高速実行
AppleScript名:offset ofの高速実行 |
set aDate to current date repeat 100000 times set aStr to "abcdefghi" set aRes to offset of "c" in aStr end repeat set bDate to current date –結果表示 display dialog (bDate – aDate) as string –> 通常で5秒、offset ofをフックして自前のサブルーチンで実行すると2秒 –offset命令の実行を横取りする on offset of searchStr in str set aRes to getOffset(str, searchStr) of me return aRes end offset on getOffset(str, searchStr) set d to divideBy(str, searchStr) if (count d) is less than 2 then return 0 return (length of item 1 of d) + 1 end getOffset on divideBy(str, separator) set delSave to AppleScript’s text item delimiters set the AppleScript’s text item delimiters to separator set strItems to every text item of str set the AppleScript’s text item delimiters to delSave return strItems end divideBy |
文字列中に指定した文字列があるか検索する
AppleScript名:文字列中に指定した文字列があるか検索する |
— Created 2015-01-26 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set aString to current application’s NSString’s stringWithString:"長野谷 隆昌" set aRange to aString’s rangeOfString:"隆" return aRange –>{location:4, length:1} if aRange’s location() = current application’s NSNotFound then current application’s NSLog("Not Found") else current application’s NSLog("Found") end if |
テキストの複数検索(ファイルから読み込んで検索)
AppleScript名:テキストの複数検索(ファイルから読み込んで検索) |
— Created 2017-08-09 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" property NSString : a reference to current application’s NSString property NSMutableArray : a reference to current application’s NSMutableArray property NSDate : a reference to current application’s NSDate property NSLiteralSearch : a reference to current application’s NSLiteralSearch set aFile to POSIX path of (choose file) set a1Dat to NSDate’s timeIntervalSinceReferenceDate() set aStr to NSString’s stringWithContentsOfFile:aFile encoding:(current application’s NSUTF8StringEncoding) |error|:(missing value) set aRes to searchWordRanges(aStr, "子供") of me as list –> {{location:1159, length:2}, {location:1242, length:2}, {location:1261, length:2}, ….. set b1Dat to NSDate’s timeIntervalSinceReferenceDate() set c1Dat to b1Dat – a1Dat on searchWordRanges(aTargText as string, aSearchStr as string) set aStr to NSString’s stringWithString:aTargText set bStr to NSString’s stringWithString:aSearchStr set hitArray to NSMutableArray’s alloc()’s init() set cNum to (aStr’s |length|()) as integer set aRange to current application’s NSMakeRange(0, cNum) repeat set detectedRange to aStr’s rangeOfString:bStr options:(NSLiteralSearch) range:aRange if detectedRange’s location is equal to current application’s NSNotFound then exit repeat hitArray’s addObject:detectedRange set aNum to (detectedRange’s location) as integer set bNum to (detectedRange’s |length|) as integer set aRange to current application’s NSMakeRange(aNum + bNum, cNum – (aNum + bNum)) end repeat return hitArray end searchWordRanges |
テキストのキーワード検索(結果をNSRangeのlistで返す)
AppleScript名:テキストのキーワード検索(結果をNSRangeのlistで返す) |
— Created 2017-08-09 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" –http://piyocast.com/as/archives/4771 property NSString : a reference to current application’s NSString property NSMutableArray : a reference to current application’s NSMutableArray property NSLiteralSearch : a reference to current application’s NSLiteralSearch set aStr to "ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC ATGC ACGT ATGC AGTC " set aRes to searchWordRanges(aStr, "ATGC") of me as list –> {{location:0, length:4}, {location:10, length:4}, {location:20, length:4}, {location:30, length:4}, {location:40, length:4}, {location:50, length:4}, {location:60, length:4}, {location:70, length:4}} on searchWordRanges(aTargText as string, aSearchStr as string) set aStr to NSString’s stringWithString:aTargText set bStr to NSString’s stringWithString:aSearchStr set hitArray to NSMutableArray’s alloc()’s init() set cNum to (aStr’s |length|()) as integer set aRange to current application’s NSMakeRange(0, cNum) repeat set detectedRange to aStr’s rangeOfString:bStr options:(NSLiteralSearch) range:aRange if (detectedRange’s location) is equal to (current application’s NSNotFound) then exit repeat hitArray’s addObject:detectedRange set aNum to (detectedRange’s location) as integer set bNum to (detectedRange’s |length|) as integer set aRange to current application’s NSMakeRange(aNum + bNum, cNum – (aNum + bNum)) end repeat return hitArray end searchWordRanges |
テキストからリガチャーを削除する v2
AppleScript名:テキストからリガチャーを削除する v2 |
— Created 2017-01-17 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" set inputStringWithLigatures to "ꜲꜳÆæꜴꜵꜶꜷꜸꜹꜺꜻꜼꜽffffifflfiflŒœꝎstꜨꜩᵫꝠꝡ" & "LJLjNJNjnjDZDzdzIJij" set aRes to removeLigaturesFromString(inputStringWithLigatures) of me –> "AAaaAEaeAOaoAUauAVavAVavAYayffffifflfiflOEoeOOstTZtzueVYvyLJLjNJNjnjDZDzdzIJij" on removeLigaturesFromString(inputStringWithLigatures) set theString to current application’s NSString’s stringWithString:inputStringWithLigatures # Convert what may be done applying transform "ÆæffffifflfiflŒœᵫ" & "LJLjNJNjnjDZDzdzIJij" set inputStringWithLigatures to (theString’s stringByApplyingTransform:"Latin-ASCII" |reverse|:false) as text # Treat the remaining ligatures set searchStrings to {"Ꜳ", "ꜳ", "Ꜵ", "ꜵ", "Ꜷ", "ꜷ", "Ꜹ", "ꜹ", "Ꜻ", "ꜻ", "Ꜽ", "ꜽ", "Ꝏ", "Ꜩ", "ꜩ", "Ꝡ", "ꝡ"} — if you find others, add them here set replaceStrings to {"AA", "aa", "AO", "ao", "AU", "au", "AV", "av", "AV", "av", "AY", "ay", "OO", "TZ", "tz", "VY", "vy"} — if you find others, add them here set saveTID to AppleScript’s text item delimiters considering case set i to 0 repeat with lig in searchStrings set i to i + 1 set AppleScript’s text item delimiters to {lig} set inputStringWithLigatures to text items of inputStringWithLigatures set AppleScript’s text item delimiters to {item i of replaceStrings} set inputStringWithLigatures to inputStringWithLigatures as text end repeat end considering set AppleScript’s text item delimiters to saveTID return inputStringWithLigatures end removeLigaturesFromString |
文字置換 v2
指定文字列の中の文字(文字列)を置換するAppleScriptです。
Cocoaの機能を用いる方法よりも速く置換できます。文字置換に関してはこのルーチンが最速です。
Text Item Delimitersを使って文字置換を行うことに対して「納得できない」といった感想を持つ人もいるようですが、本ルーチンのように機能単位でカプセル化してしまえば、Text Item Delimitersを毎度毎度記述する必要はありません。実際に、自分も「Text Item Delimiters」をほとんどキーボードから入力したことはありません。
また、たまーに間違った使われ方を目にするのですが、本ルーチンは対象となるテキストを一括置換するので、「10箇所置換箇所があるから10回ループで回す必要がある」わけではありません。1回だけで全部置換できます。
本ルーチンよりもCocoa呼び出しの処理が高速になるのは、数10Kバイトを超える長大なテキストを処理する場合です。ちょっとした、256バイト以下の短い文字列を置換するような用途では本ルーチンで事足ります。
また、Cocoa系の文字置換ルーチンでは一部の特殊文字を置換できないので、そういう文字を置換する場合にも本ルーチンを使用します。
正規表現を用いる場合には、Cocoa系の文字置換処理を呼び出すのがよいでしょう。
AppleScript名:文字置換 v2 |
set a to repChar("thi^ is a ^", "^", "_") of me a –文字置換 on repChar(origText as string, targChar as string, repChar as string) set curDelim to AppleScript’s text item delimiters set AppleScript’s text item delimiters to targChar set tmpList to text items of origText set AppleScript’s text item delimiters to repChar set retText to tmpList as string set AppleScript’s text item delimiters to curDelim return retText end repChar |
ASOCで文字置換5
AppleScript名:ASOCで文字置換5 |
— Created 2015-06-30 by Takaaki Naganoya use AppleScript version "2.4" use scripting additions use framework "Foundation" set a to "あいうえお++かきくけこ" set b to cleanUpText(a, "+", "●") –> "あいうえお●●かきくけこ" on cleanUpText(someText, targStr, repStr) set theString to current application’s NSString’s stringWithString:someText set targString to current application’s NSString’s stringWithString:targStr set repString to current application’s NSString’s stringWithString:repStr set theString to theString’s stringByReplacingOccurrencesOfString:targString withString:repString options:(current application’s NSRegularExpressionSearch) range:{location:0, |length|:length of someText} return theString as text end cleanUpText |
横書きテキストを縦書きに変換 v6
AppleScript名:横書きテキストを縦書きに変換 v6 |
— Created 2017-10-03 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" –http://piyocast.com/as/archives/4875 property NSArray : a reference to current application’s NSArray property NSString : a reference to current application’s NSString property NSStringTransformFullwidthToHalfwidth : a reference to current application’s NSStringTransformFullwidthToHalfwidth property NSMutableArray : a reference to current application’s NSMutableArray on run set lineMax to 9 set aText to "テキスト縦書きを行うAppleScriptの「禁則処理」および任意改行への対応バージョンです。" set sRes to makeTategakiStr(lineMax, aText) of me end run –縦行数を指定しつつ指定テキストを縦書き化 on makeTategakiStr(lineMax as integer, aText as string) set curMax to 0 set sList to paragraphs of aText –途中で強制改行が入っているケースに対処 set aList to {} repeat with i in sList set outList to strToTategakiList(lineMax, i) of me set the end of aList to outList end repeat set aList to kinsokuList2(aList) of me set curLen to length of aList set curMax to getMaxItemCountFrom2DArray(aList) of me set tmpList to {} set twoDList to make2DBlankArray(curLen, curMax) of me set curY to 1 repeat with x from 1 to curMax set curX to 1 repeat with y from curLen to 1 by -1 set aCon to getItemByXY(x, y, aList, " ") of me set twoDList to setItemByXY(curX, curY, twoDList, aCon as string) of me set curX to curX + 1 end repeat set curY to curY + 1 end repeat — set twoDList2 to checkBlankVerticalLine(twoDList, " ") set aRes to list2dToStringByUsingDelimiters(twoDList2, " ", return) of me set zRes to hanToZen(aRes) of me return zRes end makeTategakiStr –与えた文字列を縦書き2Dリストに変換 on strToTategakiList(lineMax as integer, aText as string) set zText to hanToZen(aText) of me set outList to {} set oneLine to {} set aCount to 1 set curMax to 0 repeat with i from 1 to (length of aText) set aChar to character i of aText set aChar to retTateChar(aChar) of me set the end of oneLine to aChar set aCount to aCount + 1 if aCount > lineMax then set aCount to 1 set the end of outList to oneLine set oneLine to {} end if end repeat if oneLine is not equal to {} then set the end of outList to oneLine end if return outList end strToTategakiList –半角→全角変換 on hanToZen(aStr as string) set aString to NSString’s stringWithString:aStr return (aString’s stringByApplyingTransform:(NSStringTransformFullwidthToHalfwidth) |reverse|:true) as string end hanToZen –2D Listに配列の添字的なアクセスを行なってデータを取得 on getItemByXY(aX as integer, aY as integer, aList as list, aBlankItem) –1 based index try set aContents to contents of (item aX of item aY of aList) on error set aContents to aBlankItem end try return aContents end getItemByXY –2D Listに配列の添字的なアクセスを行なってデータを設定 on setItemByXY(aX as integer, aY as integer, tmpList as list, aContents) –1 based index set (item aX of item aY of tmpList) to aContents return tmpList end setItemByXY –空白の2D Array を出力する on make2DBlankArray(curLen as integer, curMax as integer) set outArray to {} repeat curMax times set tmpList to {} repeat curLen times set the end of tmpList to "" end repeat set the end of outArray to tmpList end repeat return outArray end make2DBlankArray –2D Listをアイテム間デリミタ、および行間デリミタを指定しつつテキスト化 on list2dToStringByUsingDelimiters(aList as list, itemDelimiter as string, lineDelimiter as string) set outList to {} repeat with i in aList set aStr to listToStringUsingTextItemDelimiter(i, itemDelimiter) of me set the end of outList to aStr end repeat return listToStringUsingTextItemDelimiter(outList, lineDelimiter) of me end list2dToStringByUsingDelimiters –1D Listをアイテム間デリミタ、および行間デリミタを指定しつつテキスト化 on listToStringUsingTextItemDelimiter(sourceList as list, textItemDelimiter as string) set anArray to NSArray’s arrayWithArray:sourceList return (anArray’s componentsJoinedByString:textItemDelimiter) as string end listToStringUsingTextItemDelimiter –2D Listの各要素のアイテム数のうち最多のものを返す on getMaxItemCountFrom2DArray(aList as list) set anArray to NSArray’s arrayWithArray:aList set bArray to (anArray’s valueForKeyPath:"@unionOfObjects.@count") return (bArray’s valueForKeyPath:"@max.self") as integer end getMaxItemCountFrom2DArray –特殊文字の横書き用から縦書き用への置き換え on retTateChar(aChar as string) if aChar = "<" then return "︿" if aChar = ">" then return "﹀" — if aChar = "《" then return "︽" if aChar = "》" then return "︾" — if aChar = "「" then return "﹁" if aChar = "」" then return "﹂" — if aChar = "『" then return "﹃" if aChar = "』" then return "﹄" — if aChar = "【" then return "︻" if aChar = "】" then return "︼" — if aChar = "[" then return "﹇" if aChar = "]" then return "﹈" — if aChar = "{" then return "︷" if aChar = "}" then return "︸" — if aChar = "(" then return "︵" if aChar = ")" then return "︶" — if aChar = "、" then return "︑" if aChar = "。" then return "︒" if aChar = "ー" then return "︱" if aChar = "~" then return "⌇" if aChar = "=" then return "‖" — if aChar = "1" then return "一" if aChar = "2" then return "二" if aChar = "3" then return "三" if aChar = "4" then return "四" if aChar = "5" then return "五" if aChar = "6" then return "六" if aChar = "7" then return "七" if aChar = "8" then return "八" if aChar = "9" then return "九" if aChar = "0" then return "〇" return aChar end retTateChar –とりあえずな禁則処理(任意改行を考慮し、2D Listでデータを受け取る) on kinsokuList2(toDList as list) set kinsokuCharList to {"︒", "︑", "﹁", "﹂", "﹃", "﹄", "︻", "︼", "﹇", "﹈", "︷", "︸", "︵", "︶", "︱", "⌇", "ァ", "ィ", "ゥ", "ェ", "ォ", "ョ", "ぁ", "ぃ", "ぅ", "ぇ", "ぉ", "ょ"} set outList to {} repeat with ii in toDList set aList to contents of ii set aLen to length of aList set startNum to 2 repeat set chgF to false repeat with i from startNum to aLen try set aChar to contents of first item of item i of aList on error –ちょっと強引、、、 exit repeat end try considering case and diacriticals –超重要!! if aChar is in kinsokuCharList then –行頭に禁則文字が入っていたら、前の行に追い出す set the end of item (i – 1) of aList to aChar set tmpList to contents of item i of aList set item i of aList to removeItemInArray(tmpList, 1) of me –リフロー処理 –repeat with refI from (i + ((i < aLen) as integer)) to aLen repeat with refI from (i + 1) to aLen –現在行の先頭の文字を取得 set aaChar to first item of item refI of aList –前行の末尾に追加 set the end of item (refI – 1) of aList to aaChar –現在行の先頭の文字を削除 set tmpList to contents of item refI of aList set item refI of aList to removeItemInArray(tmpList, 1) of me end repeat if chgF = false then set chgF to true copy (i + ((aLen > i) as integer)) to startNum end if end if end considering –超重要!! end repeat if chgF = false then exit repeat end repeat set outList to outList & aList end repeat return outList end kinsokuList2 on removeItemInArray(aList as list, anItemNo as integer) set anArray to NSMutableArray’s arrayWithArray:aList anArray’s removeObjectAtIndex:(anItemNo – 1) return anArray as list end removeItemInArray on offsetOf(aList as list, aTarg) set aArray to NSArray’s arrayWithArray:aList set aIndex to aArray’s indexOfObjectIdenticalTo:aTarg return ((aIndex as integer) + 1) end offsetOf –縦方向に空白行が存在していたら削除、末尾からスキャン on checkBlankVerticalLine(aList as list, aBlankChar as string) set tLen to length of (item 1 of aList) copy aList to bList set hitList to makeRepeatinglList(length of bList, true) of me set aCount to 1 repeat –縦方向に1行分、すべて空白文字かどうかチェック set workList to {} repeat with ii in bList set jj to contents of ii set the end of workList to (item aCount of jj = aBlankChar) end repeat –縦方向に1行空白だったら、1行分の削除を行う if workList = hitList then repeat with ii from 1 to length of bList set jj to contents of item ii of bList set item ii of bList to removeItemInArray(jj, 1) of me end repeat set tLen to tLen – 1 end if set aCount to aCount + 1 if aCount > tLen then exit repeat end if end repeat return bList end checkBlankVerticalLine –指定アイテムを指定個数連結したリストを作成 on makeRepeatinglList(hitNum as integer, hitItem) set outList to {} repeat hitNum times set the end of outList to hitItem end repeat return outList end makeRepeatinglList |
セリフの文章のみを抽出する v1
AppleScript名:セリフの文章のみを抽出する v1 |
use AppleScript version "2.4" use scripting additions use framework "Foundation" set sourcePath to choose file tell current application set aStr to (read sourcePath as «class utf8») end tell findPatternAndReturnRanges("^「.{3,90}」$", aStr, false) of me on replaceString(thePattern, theString, theTemplate) set theOptions to ((current application’s NSRegularExpressionDotMatchesLineSeparators) as integer) + ((current application’s NSRegularExpressionAnchorsMatchLines) as integer) set theRegEx to current application’s NSRegularExpression’s regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value) set theResult to theRegEx’s stringByReplacingMatchesInString:theString options:0 range:{location:0, |length|:length of theString} withTemplate:theTemplate return theResult as text end replaceString on findPatternAndReturnRanges(thePattern, theString, rangeFlag) set theOptions to ((current application’s NSRegularExpressionDotMatchesLineSeparators) as integer) + ((current application’s NSRegularExpressionAnchorsMatchLines) as integer) set theRegEx to current application’s NSRegularExpression’s regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value) set theFinds to theRegEx’s matchesInString:theString options:0 range:{location:0, |length|:length of theString} set theFinds to theFinds as list — so we can loop through log {"Found Number:", length of theFinds} set theResult to {} — we will add to this set theNSString to current application’s NSString’s stringWithString:theString repeat with i from 1 to count of items of theFinds set theRange to (item i of theFinds)’s range() if rangeFlag = true then set end of theResult to theRange else set foundStr to (theNSString’s substringWithRange:theRange) as string set end of theResult to foundStr log {"Found String:", foundStr} end if end repeat return theResult end findPatternAndReturnRanges on findPattern:thePattern inString:theString capturing:n set theOptions to ((current application’s NSRegularExpressionDotMatchesLineSeparators) as integer) + ((current application’s NSRegularExpressionAnchorsMatchLines) as integer) set theRegEx to current application’s NSRegularExpression’s regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value) set theFinds to theRegEx’s matchesInString:theString options:0 range:{location:0, |length|:length of theString} set theFinds to theFinds as list — so we can loop through set theResult to {} — we will add to this set theNSString to current application’s NSString’s stringWithString:theString repeat with i from 1 to count of items of theFinds set oneFind to (item i of theFinds) if (oneFind’s numberOfRanges()) as integer < (n + 1) then set end of theResult to missing value else set theRange to (oneFind’s rangeAtIndex:n) set end of theResult to (theNSString’s substringWithRange:theRange) as string end if end repeat return theResult end findPattern:inString:capturing: |