以下是使用JSL調試器解決問題的案例研究。這是基於指定問題的真實腳本。如果你想在上下文中看到問題,我創建了一個腳本 - 從原始腳本中簡化 - 顯示了問題。如果您想“一起玩”,可以下載 DebuggerDemo-SolvingProblems.jsl 來自JMP文件交換(下載所需的免費SAS配置文件)。
雖然我正在描述原始腳本,但代碼片段和圖片都來自此示例腳本。跟著!
問題
前幾天,一個遇到腳本問題的JSL腳本編寫者被指示給我尋求幫助。她的腳本用英文運行得很好,但是用簡體中文運行她的腳本的測試人員卻出錯了。
問題似乎與英語與中文處理字符串的方式有關:具體來說,是逃脫的引號( \“!被遺棄了。
在英語中,這是一個構造的示例字符串:
“dt <<選擇位置(dt:Numbers == 45&dt:Pick Strings == \!”South \!“)”
在中文中,字符串看起來像這樣:
“dt <<選擇位置(dt:Numbers == 45&dt:Pick Strings == South)”
注意缺少 \!“...... \”!周圍南 ,在解析字符串時導致錯誤,並且無法解析未引用的值。
當使用英語以外的語言處理字符串中的引號時,JMP中是否存在錯誤?
第一眼
她向我發送了運行它所需的腳本和數據。該劇本只缺少900行,並製作了一份互動報告。設置了前130行,第131-886行定義了表達式,然後腳本的其餘部分使用了這些表達式。
我做的第一件事是用英文然後用中文運行腳本,看看我是否有同樣的問題。我做到了。然後我用法語運行它,證實問題出在任何非英語語言,而不僅僅是中文。我用英語和法語進行了剩下的測試,因為法語對我來說比中文更容易閱讀。
小費: 在Windows上切換正在運行JMP的語言很容易。選擇文件>首選項,然後選擇Windows特定類別。在頂部,選擇顯示語言下的語言。在Macintosh上,首先退出JMP,然後打開“系統偏好設置”(在Apple菜單上),並選擇“語言和文本”類別。將新語言拖到列表頂部。不要關閉這個窗口!它為您的計算機設置語言。啟動JMP,它將以列表中的第一種語言運行。完成後,退出JMP並將英語(或您通常在計算機上使用的任何語言)拖到頂部。現在關閉“系統偏好設置”窗口是安全的。
有幾行構造了上面的字符串,它們都依賴於相當複雜的編碼,這些編碼在逐行執行,進入和退出多個表達式以及理解我正在查看的內容時會非常困難和耗時。
僅運行適當的字符串構建行(在腳本運行一次以初始化所有這些變量之後)在所有語言中都給出了相同的結果,並正確使用了轉義引號。但是,形成字符串的行使用了來自兩個數據表的值加上從前兩個數據表構造的第三個數據表,並且很難一目了然地說明所使用的所有變量的創建和填充。
換句話說,這是JSL調試器的工作!
輸入JSL調試器
用英文運行JMP,我打開腳本並單擊Debug。由於我已經運行了腳本,因此它的所有變量都列在Globals下。並且有很多 - 當我瀏覽腳本時,跟踪的內容太多了。(我也可以通過跑步發現這一點顯示全球 () 並且看著日誌變長很長。)
這就是我當時需要知道的全部內容,所以我退出JSL調試器並退出並重新啟動JMP,以便我的環境現在完全乾淨。我打開腳本,再次啟動調試器。
我只對正在構建的字符串感興趣,所以我將該變量添加到我的監視列表中。為此,我在腳本中選擇了變量,如JSL調試器中所示,右鍵單擊並選擇Add Watch。

我在設置部分完成後在第一行添加了一個斷點(原始的第131行;我的樣本中的第34行),在創建所有表達式後的第一個“真實”指令行中添加另一個斷點(第887行)原始;這在我的樣本中不存在)。為此,我單擊調試器中顯示的腳本中的行號旁邊。

小費: 只有將斷點放在執行某些操作的行上時,斷點才有效。空行處的斷點,僅包含閉括號的行或將被註釋掉的行將被忽略。
我運行了第一個“設置”部分,看到我的字符串變量尚未創建。我只需點擊一下就知道了 - 比我手動逐行運行腳本要快得多!
我運行了第二部分,它只是創建了所有表達式。
現在是採取行動的時候了。
腳本的“肉”包含在原始腳本的底部,只有10行。第一部分是一個循環,它調用了幾個表達式(稱為表達式,稱為表達式等)。我使用Step Into按鈕逐步進入每個表達式,以找出發生了什麼。
小費: 在表達式,用戶定義的函數或。時使用Step Over 包括 () 被調用,完整地運行該代碼,返回其結果,並將執行點放在下一行。如果您不需要逐行執行,這是跳過您不需要的快速方法。另一方面,有時您需要確切地查看該表達式,函數或包含的腳本正在做什麼。相反,請使用Step Into,您將能夠逐行瀏覽該段代碼。
結果
我發現的是每一根繩子都是在一根繩子裡面建造的如果 () 表達式:如果包含信息的列是字符,則使用轉義引號引用該值;否則,該值未被引用。
這也意味著,在近900行代碼中,我真的只對19行中的一小部分感興趣(但仍然依賴於其他800行)。在我的樣本中,在第38-54行重新創建(和簡化)這些行。
我將JMP更改為以法語運行,退出並重新啟動,然後再次通過調試器。
突然間,一切都清楚了......
JMP是本地化的!(誰知道?)
問題不在於構建字符串的賦值。我在調試器中看到的問題是,在法語中,條件是在如果 () 確定列是否確定列是否為字符的表達式不字符。對於字符列,腳本使用法語執行與英語不同的代碼點。
事實上,法語的條件總是會回歸 0 。條件的一部分如果 () 表達式是這樣的(我的樣本中的第40和48行):
解析 ( “DT” || COLUMNNAMES [ thisCol ] ) << 獲取數據類型 () == “字符”
用英語講,關口 << 獲取數據類型 () 回報 “字符” 對於字符列。在法語中,它返回 “Caractère” ,永遠不會評價為等於 “字符” 。
關口 << 獲取數據類型 () 始終返回本地化答案。
由於有問題的列從未被確定為等於 “字符” 當用中文(或法語或JMP支持的英語以外的任何語言)運行時,字符串的構造就像單元格值是數字一樣。這就是為什麼英語中的字符串沒有引用引號而中文中的字符串沒有。
注意: 雖然JSL Debugger沒有顯示結果 << 獲取數據類型 () 消息 - 只有比較的結果 - 我可以輕鬆退出調試器,然後選擇並運行解析 ( “DT” || COLUMNNAMES [ thisCol ] ) << 獲取數據類型 () 看看實際返回了什麼。調試器使我能夠快速,輕鬆地找到問題。
呼籲採取行動
JMP中沒有錯誤:這是按設計工作的。該腳本只需要進行一些小改動即可使用任何語言。
有不止一種方法可以使腳本跨語言友好。你會怎麼做?我將在一兩週內添加我們對評論所採用的方法。