2017-05-12 1 views
2

私はこの宿題の質問で過去3時間苦労していて、どこにも出てこないようです。私はオンラインで検索し、YouTubeの動画を見ました。テキストファイルを読み込んで特定の単語を置き換えて別の名前でテキストファイルを出力するプログラムを書く方法

質問: 以下に添付されているinput.txtファイルを読み込み、output.txtという名前の新しいファイルを書き込むPerlプログラムを作成します。新しいファイルは、文字列 'new'を 'old'に置き換えます(大文字小文字に関係なく)。

これは私がこれまで持っていたものですが、どこにも登場しないようです。

use strict; 
use warnings; 

my $filename = 'WK5input.txt'; 
open(my $fh, $filename) 
    or die "Could not open file '$filename' $!"; 

while (my $row = <$fh>) { 
    chomp $row; 
    print "$row\n"; 
} 

$_ =~ s/new/old/g; 
open($fh, '>', 'output.txt'); 

print $filename ; 
close $filename; 
+1

@AruneshSingh '-i'を使用すると、明示的に必要とするOPに矛盾するように見えます。 – Yunnosch

+0

OP、別のperlスクリプトが必要です(例のように)か、コマンドラインの一行も役立ちますか? – Yunnosch

+0

スクリプトからファイルを読み込んで新しいファイルに書き込むか、シェルリダイレクトを使用できますか? – Yunnosch

答えて

1

:あなたの宿題の特殊な状況では
perl -pe "s/new/old/gi" WK5input.txt > output.txt

は、しかし、あなたは合理的な目標に近いが、多くなりました少しの細かい部分を修正しなければならなかった。
(これらの詳細、大文字と小文字の区別がありませんでしたが、適切なサンプル入力と希望の出力を提供していれば、それは起こりませんでした)[doc] [mcve]を読んでみてください)
私は効率的なソリューションを作るために特別な副要件があなたの課題と通常の目標とを区別するための前提条件。

私はあなたのバージョンの作業を上記の最適化されたバージョンよりも役立つ小さな変更があると考えているので、自分のバージョンにできるだけ近いところに解決策を提供します。それはあなたがどれくらい近づいているかを完全に隠すほどコンパクトです。
完全に最適化されておらず、宿題指向でもない中間バージョンのその他の回答を確認してください。 最適化されたソリューションでは、perlをスキップしてawkを使用したり、脳の歴史的な運動の目的でsedを使用する人もいます。

これらは、私はあなたが従うことが期待されていると思います
暗黙のルールには、いくつかの仮定を、以下のとおりです。

  • はありません、すべての要件をカバーするPerlプログラムを作成し、シェルの機能を用いないすなわち
    他のツール
  • は、コマンドラインパラメータ
    を使用していない(あなたの試みでなかったからといって、多分あなたはまだあなたのコースでそれらをカバーしていない)ラインproceによって
  • 使用ラインssing
    (ちょうどあなたの試みでそうしたからです。あなたのコースの他の方法をまだカバーしていないかもしれません)
  • "あいまいなperl magics"を使わないでください。これらの推測ルールのいずれかがあなたの譲渡には適用されない場合、彼らはそれ以外の


(「なしシェル」ルールの特殊なケース/通訳)利便性が高いにもかかわらずコマンドラインオプションは、
をしている-pe`他の答えを見てください。彼らは興味深い選択肢を提供します。

# nice touch, using these is very good practice 
use strict; 
use warnings; 

# Not necessary, but good practice: collect the "my"s in one place soon. 
# This supports self-documenting inside the code. 
# Doing it with the "my" at the first use is an aleternative option and preferred by some. 
my $filename = 'WK5input.txt'; # file name for the input file 
my $fhin;      # file handle for the input file 
my $fhout;      # file handle for the output file 
my $row;       # variable with currently processed line 

# Prefer to use the three parameter version of "open", explicitly stating the mode. 
open($fhin, '<', $filename) # two file handles are needed, use different names 
    or die 'Could not open input file "'.$filename.'" '.$!; 
# I chose to concatenate both variables (file name and failure reason) explicitly, 
# to some text inside '...', which can be more efficiently handled by perl interpreter. 
# This saves work on text inside "..." and is more self explaining, i.e. it is easier 
# to understand at the first reading what the code does. 

# The second file handle is setup here, to read from input and write to output at the same time. 
open($fhout, '>', 'output.txt') 
    or die 'Could not open output file output.txt '.$!; 

while ($row = <$fhin>) { # you are reading into a dedicated variable here ... 

    # There was the code "chomp $row;" here. 
    # This removes the newline from ther end of the line, if there is one. 
    # It is not needed if you are going to append the newline again before printing. 

    $row =~ s/new/old/gi; # ... you need to use the variable here, instead of "$_" 
    # The additional "i" behind the "g", makes the search for "new", "New", "NEW" case insensitive. 
    # Credits to other answer and comments for finding the requirement I missed. 

    # I accept the requirement to replace new->old, though it seems strange. 
    # I itched to replace old->new. 

    print $fhout $row; # print into the output file instead of to stdout 
    # You had an additional "\n" at the end, which was in fact needed, but only 
    # because of the "chomp" a few lines above. 
    # Also, you had the variable in quotes, i.e. "$row\n". That uses some time for interpreting 
    # the text inside the quotes. If you only want to print the content of a variable, then 
    # only print the variable outside of quotes. 
} 

# There was the code "$_ =~ s/new/old/g;" here, it was moved into the loop. 
# Compare to a different answer to see a solution which used a single global replace on 
# a variable with all the input. Instead, I decided to go for line by line processing in 
# a loop, because it seemed closer to your approach. 

# There was the code "open($fh, '>', 'output.txt');" here it was moved to before the loop. 
# There was the code "print $filename ;" here. It was deleted, because it seems not to be 
# required by the assignment. Printing the modified content is done line by line inside the 
# loop. 

# Closing file handles instead of file name: 
close $fhin; 
close $fhout; 

(StackOverflowのが宿題の質問のための完全なソリューションを提供すぐにしないことをお勧めします。
私は「...すでに解決に近くない宿題の質問のため」とすることを解釈する。
私はので、ソリューションを提供
最後の詳細を表示するには、十分に近いものを試してみてください。
StackOverflowは、既に見ている方法でさらに少しずつ学生を取り入れることを推奨しています、便利な方法で。opのみを提供するこの答えの一つの始まりであるタイムリーで微調整された最終版は、それらのために建設的ではありません。
これは本当に私の答えの中に本当に悪いコードの言い訳ではないので、誰もがそれを指摘すること自由に感じる。しかし編集するときは、私の目標に固執して、OPの試行に近づけてください。)

+1

変数を事前宣言しないでください。 3-arg openを使用し、2-arg openを使用しないでください。なぜあなたは '$ filename'を別々に連結しますが、' $! 'を補間しますか?代入は大文字と小文字を区別します – melpomene

+0

@fuguあなたの編集内容はいくつか修正されましたが、エラーメッセージからファイル名を削除しました(悪い)ので、大文字と小文字が区別されます。 – melpomene

+0

非常にマイナーなスタイルの点として、私は 'print {$ out} $ row;'を好んでいます。主なものにはいくつかの理由があります: 'print $ out、$ row" \ n "'は動作しますが、 'print {$ out}、$ row"は構文エラーです。 – Sobrique

-1

ちょうどこの試してみてください。複数の方法は、I/Oの処理中にタスクを実行することがあります

use strict; 
use warnings; 

my $filename = 'WK5input.txt'; 

open(my $tmp, "<", $filename) or die "Couldn't able to open a file...: $!\n"; 
my $storeline = ""; 
while(my $line = <$tmp>) 
{ 
    $line=~s/new/old/g; 
    $storeline .= $line; 
} 

open(my $out, ">", "Output.txt") or die "Couldn't able to open a file...: $!\n"; 
print $out $storeline; 
close($out); 
close($tmp); 

を。これはあなたの質問/理解の目的のみに基づいています。

whileループを閉じると、一時変数[特殊変数]もできませんでした。あなたが行うことができます(おそらくあなたの割り当てのために禁止されています)さまざまなショートカットを使用して

$_ =~ s/new/old/g; 
open($fh, '>', 'output.txt'); 
+0

OPの試行と最も違った実装をした部分について説明できますか?これは宿題の問題です(解決に近い非常に目に見える試みがあるため)解決策よりも多くの説明が必要です。 – Yunnosch

+0

_これは私が今までに持っていたものですが、どこにも登場していないようです。助けてください._すでにOPの試みがソリューションに非常に近いことは、明らかに彼らがコードで何を試しているかを知っていたことです。それでは簡単に言及し、I/OがOPEN/CLOSEで動作しています。それぞれの行がコードを説明する必要はありません。また、OPがソリューションを持っている必要があり、どこで交換しているものを交換したいのか(私は問題を挙げました)。 – ssr1012

+4

barewordファイルハンドルではなく、字句変数を使用します。 3-arg openを使用し、2-arg openを使用しないでください。開いているエラーメッセージには、必ずスクリプト名とファイル名を含めてください。変数を事前宣言しないでください。何の理由もなく '$ _'を壊してはいけません。代入は大文字と小文字を区別します – melpomene

4

これを書き込む最も簡単な方法は、「入力/出力方向」を使用することです。この機能は一般的なすべてのオペレーティングシステムで利用できます。つまり、STDINから読み込んでSTDOUTに書き込むコードを記述し、オペレーティングシステムに依存してこれらのファイルを特定のファイルに接続します。この技術を使用して

、あなたのコードは、これに削減:

#!/usr/bin/perl 

use strict; 
use warnings; 

while (<>) { 
    s/new/old/gi; 
    print; 
} 

そして、(私たちは、ファイルにこれを保存することを想定しnew2oldと呼ばれる)、我々はこのようにそれを呼び出します。

$ ./new2old <WK5input.txt> output.txt 

この私たちは、ファイルハンドルを使って厄介な作業をすべてやり直す必要がなくなり、はるかに柔軟なプログラムで終わります。例えば、このようなパイプ私たちのプログラムに他のプロセスからの出力をすることができます私たち:プログラムで

$ ls | ./new2old 

ハードコーディングのファイル名は、一般的に最善のアプローチではありません。

+0

入力の出力方向を使用すると、宿題の状況と競合しているように見えます。この割り当てには、 "input.txtファイルを読み込むプログラム"が "stdinを読み込まない"必要があります。一方、効率的なソリューションの目的のために、ファイル内のperlスクリプトを使用するのは無駄に思えますが、コマンドラインの1つのライナーで行うことができます。しかし、ケースの要件に気付いた私の尊敬。私は逃しました。 – Yunnosch

+0

私は、学生が現実世界でより有用なものを学ぶことを終了した場合、常に宿題要件をゆるやかに解釈することに常に賛成しています。 –

+0

そうです、良いケースです。しかし、学生のためのトラップを作ってはいけません。私。あなたが意識的にどこから割り当てを離れるかを説明してください。多分効率的なソリューションと宿題のためのソリューションを提供します。トピックに関するOPの質問に答える必要があります。その後Q/Aを読む他の人のために追加の情報を入れてください。 – Yunnosch

2

まずは、これが宿題であることに言及してくれてありがとう。インストラクターに、課題を完了するための助力を得たことを伝えることをお勧めします。

関連する問題