2011-07-12 186 views
1

一樣的Perl腳本,我想要做的是「history | grep keyword」,只是因爲如果我想要grep許多類型的關鍵字,所以我希望它是自動化的,我編寫了一個Perl腳本來完成所有工作,而不是通過改變關鍵字來重複這些命令,所以無論何時我想看到這些特定的命令,我都會使用Perl腳本來完成它我。在unix中,與unix命令「history | grep keyword」

我想'grep'的關鍵字就是source,ls,cd等。 只要知道如何去做,它可以以任何格式打印出來。

謝謝!我很欣賞任何評論。

+2

爲什麼使用perl腳本來自動執行unix命令?爲什麼不是一個shell腳本?或者一個簡單的別名。雖然你所節省的只是寫「歷史| grep」,所以我看到它的方式,價值是有限的。 – TLP

回答

2

修改(感謝@ CHAS - 歐文斯)

#!/bin/perl 
my $searchString = $ARGV[0]; 
my $historyFile = ".bash.history"; 
open FILE, "<", $historyFile or die "could not open $historyFile: $!"; 
my @line = <FILE>; 
print "Lines that matched $searchString\n"; 
for (@lines) { 
     if ($_ =~ /$searchString/) { 
      print "$_\n"; 
     } 
} 

#!/bin/perl 
my $searchString = $ARGV[0]; 
my $historyFile = "<.bash.history"; 
open FILE, $historyFile; 
my @line = <FILE>; 
print "Lines that matched $searchString\n"; 
for (@lines) { 
     if ($_ =~ /$searchString/) { 
      print "$_\n"; 
     } 
} 

說實話...... history | grep whatever乾淨,簡單,美觀大方; )

代碼可能不是完美的

+3

'open'的兩個參數版本是危險的。始終使用三個參數版本:'my $ historyFile =「.bash_history」;打開我的$ FH,「<」,$ historyFile或死「無法打開$ historyFile:$!」;' –

+0

乾杯 - 更新 – sdolgy

0

我想你最好寫一個perlscript這確實你喜歡的匹配(即替代grep的),但不讀歷史文件。我這樣說是因爲在退出shell之前,歷史似乎沒有被刷新到.bash_history文件。現在可能有設置和/或環境變量來控制這個,但我不知道它們是什麼。所以,如果你只寫一個perl腳本scanns STDIN爲您最喜愛的命令,你可以調用它像

history | findcommands.pl 

如果減少打字,你設置後一個shell函數或別名爲你做到這一點。

按照@keifer的要求,這裏是一個示例perl腳本,用於搜索指定的歷史記錄(或默認的一組命令)。有意思的是,您應該將dflt_cmds更改爲您最經常搜索的那些。

#!/usr/bin/perl 
my @dflt_cmds = qw(cd ls echo); 
my $cmds = \@ARGV; 
if(!scalar(@$cmds)) 
{ 
    $cmds = \@dflt_cmds; 
} 
while(my $line = <STDIN>) 
{ 
    my($num, $cmd, @args) = split(' ', $line); 
    if(grep($cmd eq $_ , @$cmds)) 
    { 
     print join(' ', $cmd, @args)."\n"; 
    } 
} 
+0

嘿,感謝您的意見。有沒有「歷史| perl_script」的參考?我不知道腳本中必須包含哪些內容。 – keifer

+0

@keifer爲您添加了一個示例perl腳本。只是檢查命令,而不是參數 – Sodved

0

這是Perl,有很多方法可以做到這一點。最簡單的大概是:

#!/usr/bin/perl 

use strict; 
use warnings; 

my $regex = shift; 
print grep { /$regex/ } `cat ~/.bash_history`; 

這將運行shell命令cat ~/.bash_history和返回輸出線路的列表。行列表然後被grep函數使用。 grep函數爲每個項目運行代碼塊並僅返回具有真實返回值的代碼塊,因此它只會返回與正則表達式匹配的行。

此代碼有幾件事情錯了,(它產生一個shell來運行cat,它在內存中保存整個文件,$regex可能包含危險的事情,等),但在一個安全的環境中,速度/內存ISN」這個問題並不是那麼糟糕。

一個更好的劇本是

#!/usr/bin/perl 

use strict; 
use warnings; 

use constant HISTORYFILE => "$ENV{HOME}/.bash_history"; 

my $regex = shift; 

open my $fh, "<", HISTORYFILE 
    or die "could not open ", HISTORYFILE, ": $!"; 

while (<$fh>) { 
    next unless /$regex/; 
    print; 
} 

此腳本使用constant,使其更容易改變它在後一日期使用哪個歷史文件。它直接打開歷史文件並逐行讀取它。這意味着整個文件永遠不會在內存中。如果文件非常大,這可能非常重要。它仍然有問題,$regex可能包含一個有害的正則表達式,但只要你是運行它的人,你只能責怪自己(但我不會讓外部用戶通過這樣的命令傳遞參數,比如說Web應用程序)。

+0

感謝您的評論,但在我的主目錄歷史記錄保存在「.history」文件而不是「.bash_history」,並且「.history」文件我不更新最新的命令我已經運行,直到xterm被關閉或需要輸入「history -S」來更新它。 – keifer

+0

'history'不是一個程序,它是shell的一部分。這意味着Perl幾乎不可能獲取仍在內存中的內容。運行和管理程序來執行搜索幾乎是你唯一的答案。一個簡單的例子就是'歷史| perl -ne'print if/\ b(?:ls | source | cd)\ b /''。這將只打印與ls,source和cd匹配的行。 –

1

,因爲它需要相當長的步驟,如果我想的grep許多類型的關鍵字

history | grep -E 'ls|cd|source' 

-P將接通的Perl兼容的正則表達式庫,如果你的grep的一個新的足夠版本。