2010-12-28 37 views
1

ダブルタブ、改行、空白を削除するperlスクリプトを作成したいと思います。Perl正規表現でダブルタブ、改行、空白を削除します

は、私がこれまで持っていることは次のとおりです。

$txt=~s/\r//gs; 
$txt=~s/ +/ /gs; 
$txt=~s/\t+/\t/gs; 
$txt=~s/[\t\n]*\n/\n/gs; 
$txt=~s/\n+/\n/gs; 

しかし、それは美しいではありません 1。はるかに少ない正規表現でこれを行うことが可能でなければならない。 2.それだけではうまくいかず、私は本当に理由を知らない。空白と空白の行(つまり、タブまたは空白のみの行)を残します。

私はしばらくそれを解決することができましたが、それは非常に遅くて醜いです。

提案がありますか?

+0

これは少し不明です。 "ab TABcTABTAB \ n \ n"のような行がある場合は、結果として何を望みますか?私は上記の "ab c \ n"と読んでいますか? – DVK

+0

言い換えれば、あなたがしたいことは間違いありません:1.ラインの途中のすべての空白(スペースやタブなど)が1つのスペースに変換されていますか? 2.行頭のすべての空白が削除されます(改行を除く)? 3.完全に空の行を削除しますか? – DVK

+0

正確に。 これはおそらく役に立ちます: $ txt = "\ n空になった行を削除します。" "\ n \ nダブルスペース、ダブルスペース、終了スペースを削除してください。\ n" "\ nと先頭。タブ\ t \ n"と同じです。 "\ tタブの先頭と複数のタブで\ t \ t \ t、最後に改行:\ n \ n \ n";最後に、実際に線を分割する3 \ n以外のすべての混乱を取り除かなければならない。したがって、ゴミ箱のテキストは、余分なnl、タブ、またはスペースなしで簡単に読めるようになります。 – Scoox

答えて

2

私はあなたのための素早い答えを試してみるために、あなたはドキュメントを見てきました(そして私は単にrtfmと言っているだけではありません)。 perldocはすばらしいツールで、便利な情報がいくつかありますが、perldoc perlrequickperldoc perlrerefをお勧めします。

まず、長いテキストを複数の行に分割し、それぞれの行を別々に操作してから、再び結合する方が簡単な場合があります。また、結合する結果を格納するために新しい配列を作成すると、空の行を簡単に除外できます。

最後に、長いテキストブロックで操作すると、そのテキストがスクリプトの外部にある可能性があります。あなたが実際にファイルを開いて、それを変数にグロブすると、私がコメントブロックとして残していることをより簡単に行うことができます。このメソッドを使用して最初のブロックをコメントにし、2番目のブロックのコメントを削除するには、3番目のブロックがどちらのメソッドにも残ります。あなたが実際にファイルを読み込んでそれを分割していると、それを行単位で読み込むために多くの作業が節約されるので、これを含めます。必要に応じて別のファイルに書き出すことができます。

#!/usr/bin/env perl 

use strict; 
use warnings; 

my @return_lines; 

### Begin "text in script" Method ### 
my $txt = <<END; 
hello world 

hello world 
hello world 
hello world 
END 
#note last two are to test removing spaces after tabs 

my @lines = split(/\n/, $txt); 
foreach my $line (@lines) { 

### Begin "text in external file" Method (commented) ### 
#my $filename = 'file.txt'; 
#open(my $filehandle, '<', $filename); 
#while (<$filehandle>) { 
# my $line = $_; 

### Script continues for either input method ### 
    $line =~ s/^\s*//; #remove leading whitespace 
    $line =~ s/\s*$//; #remove trailing whitespace 
    $line =~ s/\ {2,}/ /g; #remove multiple literal spaces 
    $line =~ s/\t{2,}/\t/g; #remove excess tabs (is this what you meant?) 
    $line =~ s/(?<=\t)\ *//g; #remove any spaces after a tab 
    push @return_lines, $line unless $line=~/^\s*$/; #remove empty lines 
} 
my $return_txt = join("\n", @return_lines) . "\n"; 

print $return_txt; 
+0

あなたの良い答えをありがとう!残念ながら、私は時にはperlreでいくつかの特別なことを理解するのに困っていますが、一般的に私は質問する前にドキュメントを読む:)。あなたの答えは非常に良いですが、私はあまり好きではないのは、ファイルを行単位で読むことを制限していることです。それは私の経験から非常に遅いです。 (私はsysreadを使う)。しかし、あなたの答えが私の問題解決に役立ったので、ありがとう! – Scoox

2

私はあなたの正確な要件を確認していないが、ここであなたが軌道に乗るかもしれないいくつかのヒントです:(!おそらくあまりにも強力)

スペースにすべての空白を圧縮するには

$txt=~s/\s+/ /g ; 

は、複数のタブを圧縮する

$txt=~s/^ +//gm ; 

行の先頭に空白を削除しますスペースに

$txt=~s/\t+/ /g ; 
+0

ありがとうございました!私は自分の必要条件を不明確にしてきました。しかし、これは私がやりたいことの一部です。 – Scoox

3

あなたは、あなたが言ったことに対応するものではない、そこにいくつかの厄介なものがあります。あなたが持っているものを分解し、おそらくそこからあなたが望むものに向かって作業することができます。

$txt=~s/\r//s; # removes a single \r from the line. Did you mean to use g on this one? 
$txt=~s/[\t ]\n//s; # match a single \t OR space right before a \n, and remove. 
$txt=~s/ +/ /gs;# match at least 2 spaces, replace with a single space 
$txt=~s/\t+/ /gs;# match at least 2 \t, replace with a single space 
$txt=~s/\n /\n/s;# remove a space immediately following a \n 
$txt=~s/\t /\t/s;# remove a space immediately following a \t 
$txt=~s/\n+/ /gs;# match at least 2 \n, replace them all with a single space 

私はあなたが達成したいと思っているものはまったくありません。

私はあなたがしたいことについて正直に不明です。私があなたの記載した意図を読んでいるように、私はすべてのダブルタブを1つのタブで置き換えたいと思っていたでしょう、すべてのダブル改行と1行改行、そしてすべてのダブルスペースとシングルスペース。私はさらに、実際にダブルスだけでなく、それらの文字を実際に実行したいと推測します。ここでは私がちょうど言ったことのための正規表現は、うまくいけばそれはあなたに何かを与える: (私もすべて\ rを削除しました)。あなた未遂の正規表現は、私はあなたの規定の欲求を読む方法と一致していないようだということを考えると

$txt=~s/\r//gs;# remove all \r 
$txt=~s/\t+/\t/gs;# replace all runs of > 1 tab with a single tab 
$txt=~s/\n+/\n/gs;# replace all runs of > 1 \n with a single \n 
$txt=~s/ +/ /gs;# replace all runs of > 1 space with a single space 

、私はあなたが本当にここに何をしたいかについて、いくつかの曖昧さがあることを疑います。正規表現がより明確になるようにするために、達成しようとしていることについてさらに考えたいと思うかもしれません。

+0

ありがとうございます!私は不明であったようですが、残念ですが、未来を学ぶでしょう:)。あなたの答えは私の問題解決に役立ったので、ありがとう! – Scoox

1

これは少し不明です。

ab TABcTABTAB \n\nのような行がある場合は、結果として何が欲しいですか?私はab c\nと上記を読んでいますか?

  1. すべての空白(スペースとタブの例えば任意の量)の単一に変換ラインの真ん中に: - DVKは、1分前に、それはあなたがしたいことを正しいこと、言い換えれば

    を編集しますスペース?

  2. 行の先頭または末尾のすべての空白が削除されました(改行を除く)?

  3. 完全に空白の行を削除しますか?

    $s =~ s/[\t ]+$//ms; # Remove ending spaces/tabs 
    $s =~ s/^[\t ]+//ms; # Remove starting spaces/tabs 
    $s =~ s/[\t ]+/ /ms; # Replace duplicate whitespace mid-string with 1 space 
    $s =~ s/^$//ms;  # Remove completely empty lines 
    

私は複数行の文字列内の行アンカーの開始/終了を使用することができるように(詳細はperdoc perlreを読んで)私は「/ MS」modifyersを使用しますのでご注意ください。

+0

申し訳ありませんが、私は十分にはっきりしていなかったようです:(あなたの答えをありがとう、これはほとんどのソリューションにつながります。私は何を得ません:なぜあなたは3行目に/ msを使用しますか?^txt =〜s/^ $ // ms;はテキスト全体の最初と最後に\ nは機能しません。なぜか分かりますか? – Scoox

+0

@ Scooxは正しい: 'm'と' s'修飾子は3番目の文には何の効果もありません。実際に 's'はドットメタキャラクタを使用していないのでステートメントの* any *には関係ありません。また、 '/^$ /'( 'm'修飾子の有無にかかわらず)は何の文字も消費しないので、4番目のステートメントは決して効果がありません。最後に、4つのステートメントすべてに 'g'修飾子がありません。 –

関連する問題