JS:从可变长度的字符串(段落)中提取部分

JS: Extracting Parts from a String (Paragraph) on variable length

My question is similar to this 但它有点复杂,我太菜鸟了,无法更改那里提供的方法。

我试过子字符串方法,但它不能工作,因为字符串的长度是可变的。

我有一个像这样的字符串:

Booking:
2 people

User Details:
Firstname Lastname
123456789 
email@domain.com
facebook.com/username

Extras:
Service1
Service2

Pricing:
00/-

Comments:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus elementum ultricies pellentesque. Sed ullamcorper orci urna, et sagittis orci rhoncus quis.

Donec laoreet neque lectus, nec congue felis cursus non. Sed ac pulvinar nunc, vel cursus nulla. Curabitur at nisl ipsum. Etiam efficitur quam tortor, id malesuada lacus laoreet ac. Cras varius felis sem, id interdum enim accumsan et. 

我需要将以下值存储为变量:

var people = 2
var name   = firstname + lastname
var phone  = 123456789
var email  = email@domain.com
var fbook  = facebook.com/username
var extras = Service1, Service2
var price  = 00
var comments = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus elementum ultricies pellentesque. Sed ullamcorper orci urna, et sagittis orci rhoncus quis.
    Donec laoreet neque lectus, nec congue felis cursus non. Sed ac pulvinar nunc, vel cursus nulla. Curabitur at nisl ipsum. Etiam efficitur quam tortor, id malesuada lacus laoreet ac. Cras varius felis sem, id interdum enim accumsan et." 

请记住,在某些情况下可能会缺少一些变量。即用户没有输入电子邮件 and/or facebook URL,因此这些行可能为空甚至缺少空换行符.

如果您觉得正则表达式太复杂(即使您不是初学者,也很难做到正确),您可以像这样使用更简单的 javascript:

var input = "Booking:\n2 people\n\nUser Details:\nFirstname Lastname\n123456789\n\nfacebook.com/username\n\nExtras:\nService1\nService2\n\nPricing:\n00/-\n\nComments:\nLorem ipsum\n\ndolor sit amet";

// the input string is split into seperate lines and stored in array "lines":

var lines = input.split("\n");

// lines[0]="Booking:", lines[1]="2 people", lines[2]="", lines[3]="User Details" ...

// The lines are split per section, and stored in 2D-array "result":
// With expect=0 we look for sections[0], which is "Bookings".
// If the line "Bookings:" is found, "expect" is incremented to 1, so that
// we're now looking for sections[1], which is "User Details", and so on...
// If a line is found that is not the expected section title, and it's not empty,
// we add the line to the current section with push().

var sections = ["Booking", "User Details", "Extras", "Pricing", "Comments"];
var expect = 0, result = [];

for (var i = 0; i < lines.length; i++) {
    if (lines[i] == sections[expect] + ":") result[expect++] = []
    else if (result.length && lines[i] != "") result[result.length - 1].push(lines[i]);
}

// result[0][0]="2 people" (first line under "Booking")
// result[1][0]="Firstname Lastname" (first line under "User Details")
// result[1][1]="123456789" (second line under "User Details")
// result[1][2]="facebook.com/username" (second line under "User Details")
// ...
// result[4][0]="Lorem ipsum" (first line under "Comments")
// result[4][1]="dolor sit amet" (third line under "Comments", empty line is skipped)

// If all 5 sections have been found, we extract the variables:

var people, name, phone = "", email = "", fbook = "", extras = "", price, comments = "";

if (result.length == 5)
{

// people = the integer number at the beginning of the 1st line of the 1st section:

    people = parseInt(result[0].shift());

// name = the 1st line of the 2nd section:

    name = result[1].shift();

// The rest of the 2nd section is searched for the phone number, email and facebook.
// Because some of these lines may be missing, we cannot simply use the 
// 1st line for phone, the 2nd line for email and the 3rd for facebook.

    while (result[1].length) {
        var temp = result[1].shift();
        if (temp.search("facebook.com/") == 0) fbook = temp
        else if (temp.search("@") > -1) email = temp
        else phone = temp;
    }

// All the lines in the 3rd section are added to string "extras".
// If the string is not empty, we put a comma between the parts:

    while (result[2].length) {
        if (extras.length) extras += ", ";
        extras += result[2].shift();
    }

// price = the floating-point number at the start of the 1st line of the 4th section:

    price = parseFloat(result[3][0].substring(1));

// All the lines in the 5th section are added to string "comments".
// If the string is not empty, we put a newline between the parts:

    while (result[4].length) {
        if (comments.length) comments += "\n";
        comments += result[4].shift();
    }
}

alert("people: " + people + "\nname: " + name + "\nphone: " + phone + "\nemail: " + email + "\nfbook: " + fbook + "\nextras: " + extras + "\nprice: " + price + "\ncomments: " + comments);

此方法使用正则表达式。它非常灵活,尤其是当您不确定输入的格式时,但它会变得相当复杂。这个版本应该可以包含额外的空格、缺失的数据、不同格式的 phone 数字、带逗号和小数点的价格、空行...

var input = "Booking:\n2 people\n\nUser Details:\nFirstname Lastname\n+32 (0)9 123.456.789\nme@example.com\nfacebook.com/username\n\nExtras:\nService1\nService2\n\nPricing:\n00/-\n\nComments:\nLorem ipsum\n\ndolor sit amet";

var people, name, phone, email, fbook, extras, price, comments, temp;

// split input into 2 parts: data and comments (because the comments could contain any 
// text, including names of sections and other things which may complicate the regex).
var parts = input.match(/^((?:.|\n)*?)\n\s*\n\s*Comments\s*:\s*\n((?:.|\n)*)/i);

if (parts && parts.length > 1)
{
    temp = parts[1].match(/\s*Booking\s*:\s*\n\s*(\d+)\s*(?:person|people)/i);
    if (temp && temp.length == 2) people = temp[1];

    temp = parts[1].match(/\s*User\s*Details\s*:\s*\n\s*(.*?)\n/i);
    if (temp && temp.length == 2) name = temp[1];

    temp = parts[1].match(/\s*User\s*Details\s*:\s*\n(?:.*\n){0,1}\s*([\s\d./()+-]+?)\s*\n/i);
    if (temp && temp.length == 2) phone = temp[1];

    temp = parts[1].match(/\s*User\s*Details\s*:\s*\n(?:.*\n){0,2}\s*(.+?@.+?)\s*\n/i);
    if (temp && temp.length == 2) email = temp[1];

    temp = parts[1].match(/\s*User\s*Details\s*:\s*\n(?:.*\n){0,3}\s*(facebook.com\/.+?)\s*\n/i);
    if (temp && temp.length == 2) fbook = temp[1];

    temp = parts[1].match(/\s*Extras\s*:\s*\n((?:.*\n?)*?)\n\s*Pricing:\s*\n/i);
    if (temp && temp.length == 2) extras = temp[1].replace(/\n+/, ", ").replace(/\n+$/, "");

    temp = parts[1].match(/\s*Pricing\s*:\s*\n\s*([$\d,.]+)/i);
    if (temp && temp.length == 2) price = temp[1];

    if (parts.length > 2) comments = parts[2];
}

alert("people: " + people + "\nname: " + name + "\nphone: " + phone + "\nemail: " + email + "\nfbook: " + fbook + "\nextras: " + extras + "\nprice: " + price + "\ncomments: " + comments);