2012-08-26 73 views
0

我想添加一行在Perl這在排序的形式有數據的文本文件。我已經看到了一些示例,說明如何在文件的末尾附加數據,但是因爲我希望數據採用有序格式。的Perl:如何添加一行來排序的文本文件

請指導我如何可以做到的。

基本上從我到目前爲止已經嘗試的: (我打開一個文件,grep它的內容,看看我要添加到文件中的行是否已經存在,如果沒有,那麼將其添加到文件中(使得數據保持在一個排序格式)

open(my $FH, $file) or die "Failed to open file $file \n"; 
@file_data = <$FH>; 
close($FH); 
my $line = grep (/$string1/, @file_data); 
if($line) { 
    print "Found\n"; 
    exit(1); 
} 
else 
{ 
    #add the line to the file 
    print "Not found!\n"; 
} 
+0

用於就地在Perl PLS編輯看[此] [1] [1]:http://stackoverflow.com/questions/12070115/reading-and-writing-to-an-existing -file-in-perl – Vijay

回答

1

既然你無論如何都要閱讀文本文件的內容,怎麼樣不同的方法?

讀取文件中的行一個接 - 酮,對比較你的目標字符串。如果你讀等於目標串線,那麼你沒有做任何事情。

否則,你最終會根據您的排序條件讀取一行「更大」比你的當前行,或者你打的文件的末尾。在前一種情況下,您只需在該位置插入字符串,然後複製其餘行。在後一種情況下,您將字符串追加到末尾。

如果您不想這樣做,您可以在@file_data中執行二進制搜索以找到要添加行的位置,而無需檢查所有條目,然後在輸出之前將其插入到數組中數組到文件。

2

以下是使用Tie::File的一種方法,以便您可以輕鬆地將該文件當作數組來處理,並使用的bsearch_str_pos函數快速查找插入點。找到插入點後,檢查該點上的元素是否與插入字符串相同。如果不是,splice它進入數組。如果是平等的,不拼接它,並且隨着untie完成了,這樣的文件被完全關閉。

use strict; 
use warnings; 
use Tie::File; 
use List::BinarySearch qw(bsearch_str_pos); 

my $insert_string = 'Whatever!'; 
my $file   = 'something.txt'; 

my @array; 
tie @array, 'Tie::File', $file or die $!; 

my $idx = bsearch_str_pos $insert_string, @array; 

splice @array, $idx, 0, $insert_string 
    if $array[$idx] ne $insert_string; 

untie @array; 

bsearch_str_pos功能從List::BinarySearchMastering Algorithms with Perl二進制搜索實現的適應。其方便的特點是,如果找不到搜索字符串,它將返回可插入的索引點,同時保持排序順序。

+0

O先生!感謝您指出您的優秀圖書館使用ginormous文件。但有一個問題:如果它 - 看起來 - 幾乎不可能實施b搜索,我們如何確定你的答案是正確的? – Chris

+1

二進制搜索顯然不是不可能正確實現 - 這是非常基本的。但是錯誤會發生,理論上講,如果很多人查看並使用了代碼,那麼發現它們的速度會更快,而不是少數人使用的一次性解決方案。源代碼是公開可用的,並且正常的錯誤報告和拉取請求是受歡迎的。 – DavidO

+0

對於想要真正做到ginormous(11gigs,300m記錄)文件的人 - 像我一樣(如果你想知道我在做什麼,請點擊https://haveibeenpwned.com/Passwords)File:tie實際上完全落在它的臉上:(100%cpu,通過屋頂的RAM使用率,瘋狂交換,在殺死我的工作站之前殺死它。 – Chris

0

下面是一個簡單的版本,從stdin(或文件名(多個)上的命令行指定)讀取並追加「字符串追加」到輸出,如果它不是在輸入找到。 Outout輸出打印在stdout上。

#! /usr/bin/perl 

$found = 0; 
$append='string to append'; 

while(<>) { 
    $found = 1 if (m/$append/o); 
    print 
} 

print "$append\n" unless ($found);; 

修改它以就地編輯文件(使用perl -i)並從命令行獲取附加字符串將非常簡單。

0

'簡單' 的一行插入線,而不使用任何模塊可以是:

perl -ni -le '$insert="lemon"; $eq=($insert cmp $_); if ($eq == 0){$found++}elsif($eq==-1 && !$found){print$insert} print' 

給予者一個list.txt其上下文是:

ananas 
apple 
banana 
pear 

輸出爲:

ananas 
apple 
banana 
lemon 
pear 
+0

這是最好的解決方案,但它確實可以提供一些可讀性。它實際上並不一定是一個班輪;您可以使用'$^I'全局變量激活就地編輯模式。 – hobbs

0
{ 
    local ($^I, @ARGV) = ("", $file); # Enable in-place editing of $file 

    while (<>) { 
    # If we found the line exactly, bail out without printing it twice 
    last if $_ eq $insert; 
    # If we found the place where the line should be, insert it 
    if ($_ gt $insert) { 
     print $insert; 
     print; 
     last; 
    } 
    print; 
    } 
    # We've passed the insertion point, now output the rest of the file 
    print while <>; 
} 

Essent除了增加了很多可讀性以外,與pavel的答案相同。請注意,$insert應該已經包含尾隨換行符。

相關問題