2010-06-18 38 views
11

OK, vì vậy tôi đang sử dụng perl để đọc trong một tệp có chứa một số dữ liệu cấu hình chung. Dữ liệu này được sắp xếp thành tiêu đề dựa trên ý nghĩa của chúng. Một ví dụ sau:Sử dụng perl để phân tách một dòng có thể chứa khoảng trắng

[vars] 

# This is how we define a variable! 
$var = 10; 
$str = "Hello thar!"; 


# This section contains flags which can be used to modify module behavior 
# All modules read this file and if they understand any of the flags, use them 
[flags] 
    Verbose =  true; # Notice the errant whitespace! 

[path] 
WinPath = default; # Keyword which loads the standard PATH as defined by the operating system. Append with additonal values. 
LinuxPath = default; 

Mục tiêu: Sử dụng dòng đầu tiên là một ví dụ "$ var = 10;", tôi muốn sử dụng chức năng chia trong perl để tạo ra một mảng chứa các ký tự "$ var "và" 10 "làm phần tử. Sử dụng dòng khác như một ví dụ:

Verbose =   true; 
    # Should become [Verbose, true] aka no whitespace is present 

này là cần thiết bởi vì tôi sẽ được xuất ra những giá trị này vào một tập tin mới (mà một mảnh khác nhau của C++ mã sẽ đọc) để nhanh chóng đối tượng từ điển. Chỉ cần cung cấp cho bạn một chút hương vị của những gì nó có thể trông giống như (chỉ cần làm cho nó lên như tôi đi cùng):

define new dictionary 
name: [flags] 
# Start defining keys => values 
new key name: Verbose 
new value val: 10 
# End dictionary

Oh, và đây là mã Tôi hiện có cùng với những gì nó đang làm (không chính xác) :

sub makeref($) 
{ 
    my @line = (split (/=/)); # Produces ["Verbose", " true"]; 
} 

Để trả lời một câu hỏi, tại sao tôi không sử dụng Config :: Đơn giản, ban đầu tôi không biết tệp cấu hình của mình trông như thế nào, chỉ những gì tôi muốn. Làm cho nó lên như tôi đã đi cùng - ít nhất là những gì có vẻ hợp lý với tôi - và sử dụng perl để phân tích các tập tin.

Vấn đề là tôi có một số mã C++ sẽ tải thông tin trong tệp cấu hình, nhưng vì phân tích trong C hoặc C++ là :(Tôi quyết định sử dụng perl. Đây cũng là bài tập tốt cho tôi vì tôi mới Vì vậy, đó là điều, mã perl này không thực sự ngoài ứng dụng của tôi, nó chỉ làm cho nó dễ dàng hơn cho mã C++ để đọc thông tin. Và, nó dễ đọc hơn (cả tệp cấu hình và tệp được tạo ra). Cảm ơn các ý kiến ​​phản hồi, nó thực sự giúp đỡ.

+1

Không sử dụng nguyên mẫu trừ khi chúng là cần thiết. Thậm chí sau đó, suy nghĩ ba lần. http://perldoc.perl.org/perlsub.html#Prototypes * Tất cả điều này rất mạnh mẽ, tất nhiên, và chỉ nên được sử dụng ở mức vừa phải để làm cho thế giới trở thành một nơi tốt hơn. * –

+0

Vui lòng xem câu trả lời của FM. Bạn thực sự không nên viết trình phân tích cú pháp tệp của riêng mình để thực hiện một công việc CPAN phổ biến và tiêu chuẩn như vậy, và tập trung vào logic ứng dụng của bạn. – Ether

Trả lời

6

Nếu bạn đang làm phân tích này như một bài tập học tập, đó là tốt. Tuy nhiên, CPAN có một số mô-đun sẽ thực hiện rất nhiều công việc cho bạn.

use Config::Simple; 
Config::Simple->import_from('some_config_file.txt', \my %conf); 
+0

Vâng, tôi thực sự phải hỏi tại sao OP sử dụng những gì rất giống với định dạng tệp cấu hình chuẩn, nhưng không sử dụng các mô-đun trình đọc tệp cấu hình chuẩn sẵn có và được kiểm tra rất tốt. (YAML là một trong những tốt để xem xét nếu Config :: Đơn giản không hoàn toàn phù hợp với định dạng mong muốn.) – Ether

+0

95% thời gian này là những gì sẽ được mong muốn. Tôi đã có một số lý do (học tập, không phải tất cả các mã của tôi là trong perl) mà làm cho nó dễ dàng hơn để làm điều đó một cách khác nhau. –

2

có vẻ như bạn đã có nó. Tước khoảng trắng trước khi chia tách.

sub makeref($) 
{ 
    s/\s+//g; 
    my @line = (split(/=/)); # gets ["verbose", "true"] 
} 
+0

Ahh nó rất rõ ràng bây giờ. Cảm ơn, tôi mới đến perl và một ngôn ngữ thực sự tuyệt vời của nó. –

+0

Bạn được chào đón. Hy vọng nó giúp. –

+0

Lạ lùng, chomp không chompp whitespaces! –

1

Mã này thực hiện thủ thuật (và hiệu quả hơn mà không đảo ngược).

for (@line) { 
    s/^\s+//; 
    s/\s+$//; 
} 
+0

bạn có thể thêm' g 'vào cuối regex để làm cho nó thay thế nhiều hơn một khoảng trắng thừa. nghĩa là 's/^ \ s + // g;' –

+0

Xin lưu ý làm nổi bật cú pháp sai lầm. – Svante

+0

Có nhiều mô-đun xử lý các phần cấu hình, các dòng nối tiếp, các biến có nhiều giá trị v.v. trên CPAN. Sử dụng một trong số chúng khi bạn học xong. Tôi thích 'Config :: Std'. @FM chỉ ra 'Config :: Simple'. –

3

split chia rẽ trên một biểu hiện thường xuyên, vì vậy bạn chỉ có thể đặt khoảng trắng xung quanh dấu = vào regex của nó:

split (/\s*=\s*/, $line); 

Bạn rõ ràng là không muốn để loại bỏ tất cả khoảng trắng, hay như vậy một dòng sẽ được tạo ra (khoảng trắng bị thiếu trong chuỗi):

$str="Hellothere!"; 

Tôi đoán rằng trên ly loại bỏ khoảng trắng từ đầu và cuối dòng là đủ:

$line =~ s/^\s*(.*?)\s*$/$1/; 

Một lựa chọn đơn giản hơn với hai câu lệnh:

$line =~ s/^\s+//; 
$line =~ s/\s+$//; 
+0

Xin lưu ý làm nổi bật cú pháp sai lầm. – Svante

+0

Đó là lý do tại sao tôi có xu hướng sử dụng 's {...} {...}' khi đăng trên SO. –

+1

's/^ \ s + //' hơi hiệu quả hơn một chút. –

0

Có thể bạn đã biết tất cả, nhưng tôi nghĩ mình sẽ thêm một chút. Nếu bạn

sub makeref($) 
{ 
    my @line = (split(/=/)); 
    foreach (@line) 
    { 
     s/^\s+//g; 
     s/\s+$//g; 
    } 
} 

thì bạn sẽ xóa khoảng trắng trước và sau cả bên trái và bên phải. Bằng cách đó, chẳng hạn như:

this is a parameter   =  all sorts of stuff here 

sẽ không có khoảng trống.

!! Cảnh báo: Có thể tôi không biết mình đang nói về điều gì !!

Các vấn đề liên quan