1 前言
最近風帆問我一個問題,也就是處理org模式中的TODO。寫一個指令碼, 主要功能是未完成的按照“重要性”與“緊急性”進行分類。然後完成的 任務列出最近一週完成的。感覺還聽有用的,我自己也經常用org模式 所以用了一晚上的時間,寫了這個指令碼,然後上午來了以後由修改了 一下。基本算是可以用了。在寫這個指令碼的過程中,通過遇到的問題 從中又學習了幾點。總結一下,方便後來檢視。
2 中文的處理
Perl處理中文會遇到亂碼的問題。我用的vim編輯器也有編碼的問題。 這裡一併總結一下。
2.1 vim相關
在vim中直接檢視檔案編碼: :set fileencoding
解決vim檢視檔案亂碼的問題:在~/.vimrc中新增一下內容:
let &termencoding=&encoding
set fileencoding=utf-8,ucs-bom,gbk,cp936
這樣vim就可以自動識別編碼。
2.2 perl 相關
網址:wyllife.blog.163.com/blog/static/4116390120112152541260
Perl實用中文處理步驟(修改版)
2011-03-15 14:05:41| 分類: PERL 相關知識 |字號 訂閱 發信人: FenRagwort (澤), 信區: Perl 標 題: Perl實用中文處理步驟(修改版) 發信站: 水木社群 (Mon Feb 14 12:52:14 2011), 轉信
(修改版 感謝Invader)
0、你至少得知道編碼是怎麼回事,utf-8、gbk是什麼意思 你的文字編輯器能顯示一個檔案是什麼編碼, 不然你要處理中文檔案,都不知道用什麼編碼開啟 不過一般就是gbk和utf8兩種,實在不行兩個都試一遍 注意也許你看到的不是gbk,而是gb2312, 這兩個使用上實際是一樣的,gbk完全包含gb2312
1、讓你的指令碼檔案本身用utf8儲存,最好養成寫任何指令碼都用utf8的習慣
2、指令碼開頭加上: use utf8; use open ":encoding(gbk)", ":std"; 意思是指令碼里的字串都用utf8處理,但是標準輸入輸出用gbk(預設的內碼表編碼) 做到這一步,指令碼里就可以直接用中文了,字串、正規表示式都沒問題
如果要開啟的檔案全部是一種編碼,如utf8,則可以加上: use open ":encoding(utf8)"; #如果檔案全是gbk,那麼承上編碼設定,此行可省略
3.1、開啟內有中文的檔案前,先要確定它的編碼, 最常見是gbk或utf8,臺灣來的可能是big5,utf16le的偶有可能,其他較少見 這樣開啟: open my $fh, "<:encoding(gbk)", "file.txt" or die; # 讀檔案 open my $fh, ">:encoding(utf8)", "file.txt" or die; # 寫檔案
如果Win32系統下開啟utf16le或be檔案,需要寫成: open my $fh, "<:raw:encoding(utf16le):crlf", "file.txt" or die; 否則會有crlf轉換的bug
3.2、也可以先開啟檔案,立刻再用binmode繫結編碼 open my $fh, "file.txt" or die; binmode($fh, ":encoding(gbk)"); 一般情況,直接在open裡指定encoding即可,有時需要先接收資料,再binmode
4、如果你的檔名是中文,有點麻煩,得這樣: use Encode qw/encode/; my $file = "2011年工作記錄.txt"; # 中英文數字混合檔名也沒問題 $file = encode("gbk", $file); # 檔名是通過標準輸出傳給命令列的,而命令列 open my $fh, "<:encoding(gbk)", $file or die;
OK,中文問題搞定了,然後該幹嘛幹嘛,除了一些以位元組為物件的操作(如seek、pack), 你就把“甲乙丙丁”當“ABCD”用吧,冇問題
X、附送小技巧: 如果你是批量處理文字檔案,那甚至可以不管中文檔名問題 比如要處理chfiles資料夾下的所有txt檔案(包含中文檔名),那麼 my @files = glob "chfiles/*.txt"; foreach my $file (@files) { # $file若print出來可能有亂碼,但是無妨 open my $fh, "<:encoding(gbk)", $file or die; while (<$fh>) { print; } }
3 時間相關
直接在下面程式中解釋 包括本地的時間函式localtime,和一個模組,Date::Calc來求兩個時間點的天數差。
4 程式解析
1: use strict; 2: use warnings; 3: use utf8; 4: use Encode; 5: use open ":encoding(utf8)",":std"; 6: use Date::Calc qw(Delta_Days); 7: use Date::Calc qw(Add_Delta_Days); 8: use Data::Dumper; 9: 10: my (%hash,%hash_finished,$renwu,$start_time); 11: my $in_in = "TODO.org"; 12: open my $in, '<', $in_in or die "cannot open\n"; 13: while(<$in>) 14: { 15: chomp; 16: my $first_line=$_; 17: next if /^#/; 18: next if /^$/; 19: if ($first_line=~m/^\* TODO/) 20: { 21: if ($first_line=~m/^\* TODO(.+):重要緊急:/) 22: { 23: $hash{"重要緊急"}{$1}="A"; 24: } 25: elsif($first_line=~m/^\* TODO(.+):重要不緊急:/) 26: { 27: $hash{"重要不緊急"}{$1}="A"; 28: } 29: elsif($first_line=~m/^\* TODO(.+):不重要緊急:/) 30: { 31: $hash{"不重要緊急"}{$1}="A"; 32: } 33: elsif($first_line=~m/^\* TODO(.+):不重要不緊急:/) 34: { 35: $hash{"不重要不緊急"}{$1}="A"; 36: } 37: } 38: elsif($first_line=~/^\* DONE/) 39: { 40: $first_line=~/^\* DONE (.+)?\s+:.+:/; 41: $renwu=$1; 42: my $second_line=<$in>; 43: chomp $second_line; 44: $second_line=~m/^CLOSED: \[([-\d]+).+]/; 45: my $third_line=<$in>; 46: $third_line=~m/^.+\[(.+).....]/; 47: $start_time=$1; 48: $hash_finished{$renwu}{$start_time}{$second_line}="A"; 49: } 50: } 51: close $in; 52: 53: 54: my $out_out = "dayreport.org"; 55: open my $out, '>', $out_out or die "failed open$!\n"; 56: 57: print $out "#+STARTUP: showall\n"; 58: print $out "#+TITLE:TODO\n"; 59: print $out "#+HTML_HEAD: <link rel=\"stylesheet\" type=\"text/css\" href=\"todo.css\" />\n"; 60: print $out "#+OPTIONS: H:3 num:nil toc:nil \\n:t \@:t ::t |:t ^:nil -:t f:t *:t \\<:t\n"; 61: print $out "#+LANGUAGE: en\n"; 62: 63: =cut 64: foreach my $key1 (keys %hash) 65: { 66: print $out "* $key1\n"; 67: foreach my $key2 (keys %{$hash{$key1}}) 68: { 69: print $out " - $key2\n"; 70: } 71: } 72: =cut 73: print $out "* 重要緊急\n"; 74: foreach my $key2 (keys %{$hash{"重要緊急"}}) 75: { 76: $key2=~s/\s+$//; 77: print $out " - $key2\n"; 78: } 79: print $out "* 重要不緊急\n"; 80: foreach my $key2 (keys %{$hash{"重要不緊急"}}) 81: { 82: $key2=~s/\s+$//; 83: print $out " - $key2\n"; 84: } 85: print $out "* 不重要緊急\n"; 86: foreach my $key2 (keys %{$hash{"不重要緊急"}}) 87: { 88: $key2=~s/\s+$//; 89: print $out " - $key2\n"; 90: } 91: print $out "* 不重要不緊急\n"; 92: foreach my $key2 (keys %{$hash{"不重要不緊急"}}) 93: { 94: $key2=~s/\s+$//; 95: print $out " - $key2\n"; 96: } 97: 98: #follow is the number of today 99: my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); 100: $mon=$mon+1; 101: $year+=1900; 102: #週一是從週日開始的,要進行一下改動 103: if ($wday==0) 104: { 105: $wday=$wday+7; 106: } 107: print $wday; 108: my %hash_day=( 109: 週日 => "0", 110: 週一 => "1", 111: 週二 => "2", 112: 週三 => "3", 113: 週四 => "4", 114: 週五 => "5", 115: 週六 => "6", 116: ); 117: 118: #用程式計算每週的起止時間,用到Date::Calc模組 119: my ($monday_year,$monday_mouth,$monday_day); 120: ($monday_year,$monday_mouth,$monday_day)=Add_Delta_Days($year,$mon,$mday,-$wday+1); 121: my ($sunday_year,$sunday_mouth,$sunday_day); 122: ($sunday_year,$sunday_mouth,$sunday_day)=Add_Delta_Days($year,$mon,$mday,7-$wday); 123: 124: print $out "\n* 本週已經完成任務: <$monday_year-$monday_mouth-$monday_day>-<$sunday_year-$sunday_mouth-$sunday_day>\n"; 125: foreach my $key1 (keys %hash_finished) 126: { 127: foreach my $key2 (keys %{$hash_finished{$key1}}) 128: { 129: foreach my $key3 (keys %{$hash_finished{$key1}{$key2}}) 130: { 131: #print "$key3\n"; 132: $key3=~m/^CLOSED: \[(\d+)-0?(\d+)-0?(\d+) (.+) .+]/; 133: my $before_year=$1; 134: my $before_mon=$2; 135: my $before_mday=$3; 136: my $before_weekday=$4; 137: #print "$before_weekday\n"; 138: #用模組來計算兩個時間相差的天數 139: my $gap=Delta_Days($before_year,$before_mon,$before_mday,$year,$mon,$mday); 140: #print "$gap\n"; 141: my $weekday=$hash_day{$before_weekday}; 142: #print "$weekday\n"; 143: if ($weekday <= $wday and $gap <= 7) 144: { 145: $key1=~s/\s+/\t/g; 146: print $out " - $key1 SCHEDULED:<$key2>\t$key3\n"; 147: } 148: else 149: { 150: next; 151: } 152: } 153: } 154: } 155: 156: close $out;