3

我正在为企业应用程序在 iOS 设备和模拟器上做一些更高级的自动化。自动化是用无浏览器的 Javascript 编写的。其中一种方法适用于设备,但不适用于模拟器,因此我需要编写一个解决方法。对于好奇的人,它是 UIATarget.localTarget().frontMostApp().preferencesValueForKey(key)。

我们需要做的是从磁盘上的 plist 文件中读取到服务器的路径(不同)。作为模拟器上的解决方法,我使用以下几行来定位包含首选项的 plist 文件:

// Get the alias of the user who's logged in
var result = UIATarget.localTarget().host().performTaskWithPathArgumentsTimeout("/usr/bin/whoami", [], 5).stdout;

// Remove the extra newline at the end of the alias we got
result = result.replace('\n',"");

// Find the location of the plist containing the server info
result = UIATarget.localTarget().host().performTaskWithPathArgumentsTimeout("/usr/bin/find", ["/Users/"+result+"/Library/Application Support/iPhone Simulator", "-name", "redacted.plist"], 100);

// For some reason we need a delay here
UIATarget.localTarget().delay(.5);

// Results are returned in a single string separated by newline characters, so we can split it into an array
// This array contains all of the folders which have the plist file under the Simulator directory
var plistLocations = result.stdout.split("\n");

...

// For this example, let's just assume we want slot 0 here to save time
var plistBinaryLocation = plistLocations[0];
var plistXMLLocation =  plistLocations[i] + ".xml";
result = UIATarget.localTarget().host().performTaskWithPathArgumentsTimeout("/usr/bin/plutil", ["-convert","xml1", plistBinaryLocation,"-o", plistXMLLocation], 100);

从这里开始,我认为获取内容的最佳方法是 cat 或 grep 文件,因为我们不能直接从磁盘读取文件。但是,我无法降低语法。这是我正在阅读的 plist 文件的编辑片段:

<key>server_url</key>
<string>http://pathToServer</string>

文件中有一堆键/字符串对,其中 server_url 键是唯一的。理想情况下,我会做一些类似于回顾的事情,但由于 JavaScript 似乎不支持它,我想我只是从文件中获取这对,稍后再减少它。

我可以用这个搜索密钥:

// This line works
var expression = new RegExp(escapeRegExp("<key>server_url</key>"));

if(result.stdout.match(expression))
{
    UIALogger.logMessage("FOUND IT!!!");
}
else
{
    UIALogger.logMessage("NOPE :(");
}

escapeRegExp 方法如下所示:

function escapeRegExp(str) 
{
    var result =  str.replace(/([()[{*+.$^\\|?])/g, '\\$1');

    UIALogger.logMessage("NEW STRING: " + result);
    return result;
}

此外,此行返回一个值(但得到错误的行):

var expression = new RegExp(escapeRegExp("<string>(.*?)</string>"));

但是,当您将两者放在一起时,它(正则表达式语法)在终端上有效,但在代码中无效:

var expression = new RegExp(escapeRegExp("<key>server_url</key>[\s]*<string>(.*?)</string>"));

我错过了什么?我也尝试了 grep 和 egrep ,但没有任何运气。

4

1 回答 1

1

这里有两个问题会影响您让正则表达式在您的 JavaScript 代码中工作。

  • 首先,您正在转义整个正则表达式字符串,这意味着您的捕获(.*?)和您的空白忽略[\s]*也将被转义,并且不会按照您期望的方式进行评估。您需要转义 XML 部分并添加正则表达式部分而不转义它们。
  • 其次,忽略空格的部分[\s]*正在成为 JavaScript 正常字符串转义规则的牺牲品。“\s”在输出中变成“s”。您需要使用“\s”转义该反斜杠,以便它在您传递以构造正则表达式的字符串中保持为“\s”。

我已经构建了一个工作脚本,我已经在 UI 自动化引擎本身中进行了验证。它应该提取并打印出预期的 URL:

var testString = "" +
"<plistExample>\n" +
"   <key>dont-find-me</key>\n" +
"   <string>bad value</string>\n" +
"   <key>server_url</key>\n" +
"   <string>http://server_url</string>\n" +
"</plistExample>";

function escapeRegExp(str) 
{
    var result =  str.replace(/([()[{*+.$^\\|?])/g, '\\$1');

    UIALogger.logMessage("NEW STRING: " + result);
    return result;
}

var strExp = escapeRegExp("<key>server_url</key>") + "[\\s]*" + escapeRegExp("<string>") + "(.*)" + escapeRegExp("</string>");

UIALogger.logMessage("Expression escaping only the xml parts:" + strExp);

var exp = new RegExp(strExp);
var match = testString.match(exp);

UIALogger.logMessage("Match: " + match[1]);

不过,我应该指出,您唯一需要在正则表达式中转义的是 XML 结束标记中的正斜杠。这意味着你不需要你的escapeRegExp()函数并且可以像这样编写你想要的表达式:

var exp = new RegExp("<key>server_url<\/key>[\\s]*<string>(.*)<\/string>");
于 2013-07-15T13:31:48.267 回答