【问题标题】:Read Parameters out of icalendar file with JS使用 JS 从 icalendar 文件中读取参数
【发布时间】:2013-02-16 10:10:55
【问题描述】:

我想用 JavaScript 从 iCalendar 文件中读取几个参数。

文件输入如下:

BEGIN:VEVENT DTSTART:20121127T190000Z DTEND:20121127T210000Z DTSTAMP:20121130T185808Z UID:q4sbrtajjol1hlpiijpho5jac0@google.com 创建:20121102T191519Z 描述:1。德甲\, 14. Spieltag \n\nhttp://www.fussball-spielplan.信息最后修改:20121127T211459Z 位置:德国商业银行竞技场\,法兰克福 序列:10 状态:确认摘要:法兰克福 - 1. FSV 美因茨 05 (1:3) 运输:透明 END:VEVENT

参数标签为:

DTSTART:
DTEND:
DTSTAMP:
UID:
CREATED:
DESCRIPTION:
LAST-MODIFIED:
LOCATION:
STATUS:
SUMMARY:
TRANSP:

我想读取这些参数背后的值。 值的长度大多是可变的。

使用RegExp 非常困难,因为我目前不知道要设置什么作为分隔符。 "\n" 不起作用,因为所有文本部分都用空格分隔。 但是如果我使用空格分隔符"\s",它将在每个单词之后分开,这不是想要的结果,尤其是对于包含更长文本的参数DESCRIPTION:

我的源代码目前看起来像这样:

file_reader.onload = function (evt) {
document.getElementById("filedrag").textContent = evt.target.result;

Output(
    "<p>File information: <strong>" + file.name +
    "</strong> type: <strong>" + file.type +
    "</strong> size: <strong>" + file.size +
    "</strong> bytes</p>");

var regexp = new RegExp("/DTSTART:(.*?)\s/", "g"); 
var file_content = evt.target.result;
var match, matches = [];

while ((match = regexp.exec(file_content)) != null) {
    matches.push(match.index);
}

alert(matches);
}

任何想法,我如何实现我的想法?

【问题讨论】:

    标签: javascript regex icalendar


    【解决方案1】:

    在你的代码中

    var regexp = new RegExp("/DTSTART:(.*?)\s/", "g"); 
    

    但在将字符串传递给RegExp 构造函数时不需要正则表达式分隔符/ - 它将被解释为要匹配的字符。此外,作为字符串,任何特殊的 RegExp 字符都需要进行双重转义,因此 \s 应该是 \\s

    这是获取每个指定标签的值的一种方法:

    var match,
        matches = [],
        tags = 'DTSTART|DTEND|DTSTAMP|UID|CREATED|DESCRIPTION|' +
               'LAST-MODIFIED|LOCATION|STATUS|SUMMARY|TRANSP',
        regexp = new RegExp( '(?:' +  tags + '):([\\s\\S]*?)(?=\\s+(?:' +
                                      tags + '|SEQUENCE|END):)', 'g' );   
    
    while ( match = regexp.exec( file_content ) ) {
        matches.push( match[1] );
    }
    

    如果要检索每个标签:值对,请将match[1] 更改为match[0]

    以上假设每个标签前至少有一个空格或换行符。
    它还假设空格后跟标签名称后跟: 不会出现在任何标签的值中。

    使用[\\s\\S] 代替.,以便换行符可以包含在标签的值中。

    上面没有捕获SEQUENCE标签的值,因为它没有在列表中指定。
    如果要捕获它,只需将其添加到 tags 并从 regexp 中删除,这样 '|SEQUENCE|END):)' 就会变为 '|END):)'

    或者:

    var m,
        params = {},
        rex = /([A-Z-]+):([\s\S]*?)(?=\s+[A-Z-]+:|$)/g;   
    
    while ( m = rex.exec( file_content ) ) {
        params[ m[1] ] = m[2];
    }
    
    console.log( params["DTSTART"] );    // 20121127T190000Z
    

    【讨论】:

    • 太棒了,就像一个魅力!另外一个问题:如果我想获取 DTSTART 值以便将其用于 SQL 语句,我将如何扩展 while 条件?
    • @丹尼尔。 DTSTART 值将是数组的第一项,即matches[0]
    • @丹尼尔。我添加了一个替代版本,可以更轻松地获取每个所需的参数。
    • 以这种方式选择数组的值将要求标签的顺序始终相同。此外,每个标签都必须始终存在。在我的例子中,“BEGIN”和“END”标签是其他标签的容器。一个文件中可能有多个“BEGIN”和“END”容器。此容器中的标签可能是随机顺序的,有些可能存在或可能丢失。所以我想我需要检查每个容器是否存在所需的标签。是否可以再添加一种替代方案?
    • @丹尼尔。我添加的版本不需要标签的顺序相同或每个标签始终存在。如果有多个容器,您可以首先将容器从 BEGIN 匹配到 END,然后获取每个容器的键值对,如上所示。
    【解决方案2】:
    var params={};
    fileContent.replace(/([\w-]+):([^:]+)\s/g,function($0,$1,$2){params[$1]=$2;});
    

    上述正则表达式假定:

    • 您的参数是单个单词(无空格),后跟冒号([\w-]+):
    • 这些值不包含冒号([^:]+)

    如果您的值(例如说明文本)可以包含冒号,那么您需要更具体地了解参数(参见@MikeM 的回答)。

    现场演示:http://jsfiddle.net/zhsLJ/

    【讨论】:

    • 我喜欢这种对替换的使用,所以我 +1,但它不能正确处理 SUMMARYLAST-MODIFIED/([A-Z-]+):([\s\S]*?)(?=\s[A-Z-]+:|$)/g 怎么样。
    • @MikeM 感谢您的评论。我已更正正则表达式以接受破折号。至于SUMMARY,问题在于该值包含一个冒号,所以 - 正如我在答案中所说 - 在这种情况下,我的正则表达式不够具体,你的会更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 2014-11-08
    • 2018-04-07
    • 1970-01-01
    相关资源
    最近更新 更多