পার্লে, আমি কীভাবে একটি সম্পূর্ণ ফাইলকে স্ট্রিংয়ে পড়তে পারি?


118

আমি একটি বড় লম্বা স্ট্রিং হিসাবে একটি .html ফাইল খোলার চেষ্টা করছি। এটি আমি পেয়েছি:

open(FILE, 'index.html') or die "Can't read file 'filename' [$!]\n";  
$document = <FILE>; 
close (FILE);  
print $document;

যার ফলাফল:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN

তবে, আমি ফলাফলটি দেখতে চাই:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

এইভাবে আমি পুরো দস্তাবেজটি আরও সহজে অনুসন্ধান করতে পারি।


8
সত্যিই "ক্যান্ট ইনস্টল" এর সংজ্ঞাটি কি তা পরীক্ষা করা উচিত, এটি একটি সাধারণ সমস্যা এবং এটি সাধারণত একটি যুক্তি যা তৈরি করার প্রয়োজন হয় না। stackoverflow.com/questions/755168/perl-myths/…
কেন্ট ফ্রেড্রিক

1
এই স্ক্রিপ্টটি স্বতঃপরিচালনা বাদে এই স্ক্রিপ্টটি যে পুরো সেভারে চলছে সেটিতে আমি আসলে কোনও কিছুই সংশোধন করতে অক্ষম।
গড্ডামনৌর্যায়ন

সুতরাং আপনাকে সার্ভারে কোথাও কোনও ফাইল যুক্ত করার অনুমতি দেওয়া হচ্ছে না?
ব্র্যাড গিলবার্ট

আপনার স্ক্রিপ্ট মধ্যে ফ্যাটপ্যাক মডিউল? এছাড়াও, দেখে মনে হচ্ছে আপনি নিয়মিত প্রকাশের সাথে এইচটিএমএল পার্স করার কথা ভাবছেন, করবেন না।
এমকেভি

উত্তর:


81

যোগ করুন

 local $/;

ফাইল হ্যান্ডেল থেকে পড়া আগে। দেখুন কীভাবে আমি পুরো ফাইলটিতে একবারে পড়তে পারি? , বা

ld perldoc -q "সম্পূর্ণ ফাইল"

দেখুন filehandles এর সাথে সম্পর্কিত ভেরিয়েবল মধ্যে perldoc perlvarএবং perldoc -f local

ঘটনাক্রমে, আপনি যদি নিজের স্ক্রিপ্টটি সার্ভারে রাখতে পারেন তবে আপনার পছন্দ মতো সমস্ত মডিউল থাকতে পারে। দেখুন কীভাবে আমি আমার নিজস্ব মডিউল / গ্রন্থাগার ডিরেক্টরি রাখতে পারি?

তদ্ব্যতীত , পথ :: শ্রেণি :: ফাইল আপনাকে স্লার্প এবং স্কো করতে দেয় ।

পাথ :: ক্ষুদ্র যেমন আরও বেশি সুবিধা পদ্ধতি দেয় slurp, slurp_raw,slurp_utf8 সেইসাথে তাদের spewপ্রতিরূপ।


33
আপনার সম্ভবত স্থানীয়করণ $ / কী কী প্রভাব ফেলতে চলেছে তেমনি এর উদ্দেশ্য কী তাও ব্যাখ্যা করা উচিত।
ড্যানি

12
আপনি যদি স্থানীয়করণ সম্পর্কিত কিছু ব্যাখ্যা না দিয়ে থাকেন তবে আপনার $/আরও তথ্যের জন্য সম্ভবত লিঙ্কগুলি যুক্ত করা উচিত।
ব্র্যাড গিলবার্ট

7
কী করছে সে সম্পর্কে ধাপে ধাপে একটি ভাল ধাপ: {স্থানীয়; /; <$ fh> here
দাওজ

সম্ভবত কেবল বলুন যে আপনি অবশ্যই ব্যবহার করবেন localএবং না কেন my
জেরেমিয়া

@ জেরেমিয়া স্কোপিংয়ের একটি আলোচনা এই উত্তরের বাইরে নয়।
সিনান Ünür

99

আমি এটি এইভাবে করব:

my $file = "index.html";
my $document = do {
    local $/ = undef;
    open my $fh, "<", $file
        or die "could not open $file: $!";
    <$fh>;
};

ওপেনের ত্রি-যুক্তির সংস্করণটির ব্যবহারটি নোট করুন। এটি পুরানো দুটি (বা এক-) আর্গুমেন্ট সংস্করণগুলির চেয়ে অনেক বেশি নিরাপদ। একটি লেজিকাল ফাইলহ্যান্ডেলের ব্যবহারটিও নোট করুন। লেক্সিকাল ফাইলহ্যান্ডলগুলি বহু কারণে পুরানো খালি শব্দ বৈকল্পিকগুলির চেয়ে সুন্দর। আমরা তাদের এখানে একটির সুবিধা নিচ্ছি: তারা সুযোগের বাইরে গেলে তারা বন্ধ করে দেয়।


9
এটি সম্ভবত এটি সেরা নন-সিপ্যানড উপায় নয় কারণ এটি 3 টি যুক্তি উভয়ই খোলা রাখার পাশাপাশি INPUT_RECord_SEPARATOR ($ /) ভেরিয়েবলকে ক্ষুদ্রতম প্রয়োজনীয় প্রেক্ষাপটে স্থানীয়করণ করে।
ড্যানি

77

ওপি জানিয়েছে যে সে সার্ভারে কিছু পরিবর্তন করতে পারে না। "হ্যাঁ, এমনকি আপনি সিপিএএনও ব্যবহার করতে পারেন" লিঙ্কটি আপনাকে বেশিরভাগ ক্ষেত্রে সীমাবদ্ধতার আশেপাশে কীভাবে কাজ করবেন তা আপনাকে দেখায়।
ট্রেনটন

Can't locate File/Slurp.pm in @INC (@INC contains: /usr/lib/perl5/5.8/msys:(
দিমিত্রি

2
@ দিমিত্রি - সুতরাং মডিউলটি ইনস্টল করুন। এই উত্তরটি থেকে আমি লিঙ্কযুক্ত মেটাকপ্যান পৃষ্ঠায় একটি ইনস্টল নির্দেশিকার লিঙ্ক রয়েছে's
কোয়ান্টিন

53

সমস্ত পোস্ট সামান্য অ-অহঙ্কারী। প্রতিমাটি হ'ল:

open my $fh, '<', $filename or die "error opening $filename: $!";
my $data = do { local $/; <$fh> };

বেশিরভাগ ক্ষেত্রে, $ / to সেট করার দরকার নেই undef


3
local $foo = undefকেবল পার্ল বেস্ট অনুশীলন (পিবিপি) প্রস্তাবিত পদ্ধতি। আমরা যদি কোডের স্নিপিটগুলি পোস্ট করি তবে আমি মনে করি এটি পরিষ্কার করার জন্য যথাসাধ্য চেষ্টা করা ভাল জিনিস হবে।
ড্যানি

2
লোককে কীভাবে নন-আইডিয়োমেটিক কোড লিখবেন তা দেখানো ভাল জিনিস? যদি আমি কোডটিতে "স্থানীয় $ / = অপরিবর্তিত" দেখি তবে আমার প্রথম ক্রিয়াটি রাইকে লেখককে প্রকাশ্যে অবমাননা করা হবে। (এবং আমি সাধারণত "স্টাইল" ইস্যু সম্পর্কে পছন্দ করি না))
জারকওয়ে

1
ঠিক আছে, আমি কামড় দেব: "স্থানীয় $ / = অপরিশোধিত" সম্পর্কে মক-যোগ্য কি? যদি আপনার একমাত্র উত্তরটি "এটি অ-পরিচয়যুক্ত" হয় তবে (ক) আমি এতটা নিশ্চিত নই এবং (খ) তাই কি? আমি এতটা নিশ্চিত নই, কারণ এটি করার উপায় হিসাবে এটি অত্যন্ত ভয়ঙ্কর n এবং তাই কারণ এটি পুরোপুরি পরিষ্কার এবং যুক্তিযুক্ত সংক্ষিপ্ত। আপনি যে স্টাইলের বিষয়গুলি মনে করেন সে সম্পর্কে আপনি আরও বাছাই করতে পারেন।
টেলিমাচাস

1
মূলটি হ'ল "স্থানীয় $ /" একটি সুপরিচিত আইডিয়ামের অংশ। আপনি যদি কিছু এলোমেলো কোড লিখতে থাকেন এবং "স্থানীয় $ ফু :: বার = অপরিবর্তিত;" লিখে থাকেন তবে তা ঠিক। তবে এই খুব বিশেষ ক্ষেত্রে, আপনি অন্য সবার মতো একই ভাষায় কথা বলতে পারেন, যদিও এটি "কম স্পষ্ট" (যার সাথে আমি একমত নই; "স্থানীয়" এর আচরণ এই ক্ষেত্রে ভালভাবে সংজ্ঞায়িত হয়েছে)।
jrockway

11
দুঃখিত, একমত না আপনি যখন ম্যাজিক ভেরিয়েবলের আসল আচরণটি পরিবর্তন করতে চান তখন স্পষ্ট হওয়া অনেক বেশি সাধারণ; এটা অভিপ্রায় একটি ঘোষণা। এমনকি ডকুমেন্টেশনটি 'লোকাল $ / = অপরিবর্তিত' ব্যবহার করে ( পার্লডোক.পার্ল.আর.এল.পি.এস.পি.এস.এল.টি.এম.এল.টি.এমএল দেখুন: সমসাময়িক-মূল্যবোধগুলি- ভিওলোকাল () )
লিওনার্দো হেরেরা

19

পেরফাকাক 5 থেকে : আমি কীভাবে একবারে পুরো ফাইলটিতে পড়তে পারি? :


এক ধাপে এটি করতে আপনি ফাইল :: স্লার্প মডিউলটি ব্যবহার করতে পারেন।

use File::Slurp;

$all_of_it = read_file($filename); # entire file in scalar
@all_lines = read_file($filename); # one line per element

কোনও ফাইলের সমস্ত লাইন প্রক্রিয়াজাতকরণের জন্য প্রথাগত পার্ল পদ্ধতির ক্ষেত্রে একবারে এক লাইনের কাজটি করা:

open (INPUT, $file)     || die "can't open $file: $!";
while (<INPUT>) {
    chomp;
    # do something with $_
    }
close(INPUT)            || die "can't close $file: $!";

সম্পূর্ণ ফাইলটিকে লাইনের অ্যারে হিসাবে মেমরির মধ্যে পড়া এবং তারপরে এটি একবারে একটি উপাদানকে প্রক্রিয়াজাতকরণের চেয়ে মারাত্মকভাবে বেশি দক্ষ, যা প্রায়শই না - যদি না হয় তবে ভুল পদ্ধতির। আপনি যখনই কাউকে এটি করতে দেখেন:

@lines = <INPUT>;

আপনার কেন একবারে সমস্ত বোঝা দরকার তা নিয়ে আপনার দীর্ঘ এবং কঠোর চিন্তা করা উচিত। এটি কেবল একটি স্কেলযোগ্য সমাধান নয়। আপনি স্ট্যান্ডার্ড টাই :: ফাইল মডিউল বা ডিবি_ফাইলে মডিউলটির $ ডিবি_RECNO বাইন্ডিংগুলি ব্যবহার করতে আরও মজা পেতে পারেন যা আপনাকে কোনও ফাইলের সাথে অ্যারে টাই বাঁধার অনুমতি দেয় যাতে অ্যারের উপাদানটি অ্যাক্সেস করে ফাইলে সংশ্লিষ্ট লাইনটি অ্যাক্সেস করে ।

আপনি পুরো ফাইলহ্যান্ডেল সামগ্রীগুলি একটি স্কেলারের মধ্যে পড়তে পারেন।

{
local(*INPUT, $/);
open (INPUT, $file)     || die "can't open $file: $!";
$var = <INPUT>;
}

এটি অস্থায়ীভাবে আপনার রেকর্ড বিভাজকটিকে undefs করে এবং স্বয়ংক্রিয়ভাবে ব্লক প্রস্থান করার সময় ফাইলটি বন্ধ করে দেবে। যদি ফাইলটি ইতিমধ্যে খোলা থাকে তবে কেবল এটি ব্যবহার করুন:

$var = do { local $/; <INPUT> };

সাধারণ ফাইলগুলির জন্য আপনি পঠন ফাংশনটিও ব্যবহার করতে পারেন।

read( INPUT, $var, -s INPUT );

তৃতীয় আর্গুমেন্ট ইনপুট ফাইলহ্যান্ডেলে ডেটার বাইট আকার পরীক্ষা করে এবং পড়ে যে অনেকগুলি বাইট বাফারে। Var।


8

একটি সহজ উপায়:

while (<FILE>) { $document .= $_ }

অন্য উপায় হ'ল ইনপুট রেকর্ড পৃথককারী "$ /" পরিবর্তন করা। গ্লোবাল রেকর্ড বিভাজকটি পরিবর্তন এড়াতে আপনি স্থানীয়ভাবে এটি একটি খালি ব্লকে করতে পারেন।

{
    open(F, "filename");
    local $/ = undef;
    $d = <F>;
}

1
আপনার দেওয়া উভয় উদাহরণের সাথে একটি উল্লেখযোগ্য সংখ্যক সমস্যা রয়েছে। প্রধান সমস্যাটি হ'ল এগুলি প্রাচীন পার্লে লেখা হয়েছে, আমি মডার্ন পার্ল
ব্র্যাড গিলবার্ট

@ ব্র্যাড, মন্তব্যটি বহু বছর আগে করা হয়েছিল, বিষয়টি এখনও দাঁড়িয়ে আছে। আরও ভাল{local $/; open(my $f, '<', 'filename'); $d = <$f>;}
জোয়েল বার্গার

@ জোয়েল যা কিছুটা ভাল। আপনি আউটপুট openবা নিখুঁতভাবে কল করা চেক করেন নি closemy $d = do{ local $/; open(my $f, '<', 'filename') or die $!; my $tmp = <$f>; close $f or die $!; $tmp}। (এটিতে এখনও সমস্যা রয়েছে যে এটি ইনপুট এনকোডিং নির্দিষ্ট করে না))
ব্র্যাড গিলবার্ট

use autodie, আমি যে বড় উন্নতিটি বোঝাতে চেয়েছিলাম তা হ'ল লেক্সিকাল ফাইলহ্যান্ডল এবং 3 টি আর্গ খোলা। এটির কোনও কারণ রয়েছে do? ব্লকের আগে ঘোষিত ভেরিয়েবলে কেবল ফাইলটি ফেলে দেই না কেন?
জোয়েল বার্গার 19

7

হয় সেট করা $/হয়েছে undef(jrockway এর উত্তর দেখুন) বা কেবল ফাইলের সমস্ত লাইন একত্রিত করুন:

$content = join('', <$fh>);

এটি সমর্থন করে এমন কোনও পার্ল সংস্করণে ফাইলহ্যান্ডলগুলির জন্য স্কেলার ব্যবহার করার পরামর্শ দেওয়া হচ্ছে।



3

আপনি কেবল ডায়মন্ড অপারেটরের কাছ থেকে প্রথম লাইন পাচ্ছেন <FILE>কারণ আপনি এটিকে স্কেলার প্রসঙ্গে মূল্যায়ন করছেন:

$document = <FILE>; 

তালিকা / অ্যারে প্রসঙ্গে ডায়মন্ড অপারেটর ফাইলের সমস্ত লাইন ফিরিয়ে দেবে।

@lines = <FILE>;
print @lines;

1
নামকরণের জন্য একটি নোট: স্পেসশিপ অপারেটর <=>এবং <>হীরা অপারেটর।
সরঞ্জামিক

ওহ, ধন্যবাদ, আমি এর আগে "ডায়মন্ড অপারেটর" শুনিনি এবং ভেবেছিলাম তারা উভয়ই একই নামটি ভাগ করেছে। আমি উপরে এটি সংশোধন করব।
নাথান

2

আমি এটিকে সহজ উপায়ে করব, যাতে যে কোনও জিনিস বুঝতে পারে যে চতুর উপায় থাকলেও কী ঘটেছিল:

my $text = "";
while (my $line = <FILE>) {
    $text .= $line;
}

এই সমস্ত স্ট্রিং কনটেনটেশন বেশ ব্যয়বহুল হতে চলেছে। আমি এটি করা এড়াতে চাই। কেবল আবার একসাথে রাখার জন্য কেন ডেটা ছিঁড়ে ফেলবেন?
andru

2
open f, "test.txt"
$file = join '', <f>

<f>- আমাদের ফাইল থেকে লাইনগুলির একটি অ্যারে প্রদান করে (যদি $/ডিফল্ট মান থাকে "\n") এবং তারপরে join ''এই অ্যারেটি আটকে থাকবে।


2

এভাবেই উপরে একটি প্রস্তাবনায় বেশি হয় না এটা করতে। আমি বরং একটি বড় পার্ল অ্যাপ্লিকেশনটিতে একটি বাগ খুঁজে পেতে খুব খারাপ সময় কাটিয়েছি। মডিউলগুলির বেশিরভাগের নিজস্ব কনফিগারেশন ফাইল ছিল। সামগ্রিকভাবে কনফিগারেশন ফাইলগুলি পড়তে, আমি পার্লের এই একক লাইনটি ইন্টারনেটে কোথাও পেয়েছি:

# Bad! Don't do that!
my $content = do{local(@ARGV,$/)=$filename;<>};

এটি পূর্বে বর্ণিত হিসাবে লাইন বিভাজকটিকে পুনরায় নিয়োগ দেয়। তবে এটি এসটিডিএনকেও পুনরায় নিয়োগ দেয়।

এটির অন্তত একটি পার্শ্ব প্রতিক্রিয়া ছিল যা পেতে আমার কয়েক ঘন্টা ব্যয় করে: এটি অন্তর্ভুক্ত ফাইল হ্যান্ডেলটি সঠিকভাবে বন্ধ করে না (যেহেতু এটি কল করে না close )।

উদাহরণস্বরূপ, এটি করা:

use strict;
use warnings;

my $filename = 'some-file.txt';

my $content = do{local(@ARGV,$/)=$filename;<>};
my $content2 = do{local(@ARGV,$/)=$filename;<>};
my $content3 = do{local(@ARGV,$/)=$filename;<>};

print "After reading a file 3 times redirecting to STDIN: $.\n";

open (FILE, "<", $filename) or die $!;

print "After opening a file using dedicated file handle: $.\n";

while (<FILE>) {
    print "read line: $.\n";
}

print "before close: $.\n";
close FILE;
print "after close: $.\n";

ফলাফল স্বরূপ:

After reading a file 3 times redirecting to STDIN: 3
After opening a file using dedicated file handle: 3
read line: 1
read line: 2
(...)
read line: 46
before close: 46
after close: 0

আশ্চর্যের বিষয়টি হ'ল, $.প্রতিটি ফাইলের জন্য লাইন কাউন্টারটি এক এক করে বাড়ানো হয়। এটি পুনরায় সেট করা হয়নি, এবং এতে লাইনের সংখ্যা নেই। কমপক্ষে একটি লাইন না পড়া পর্যন্ত অন্য ফাইলটি খোলার সময় এটি শূন্যে পুনরায় সেট করা হয় না। আমার ক্ষেত্রে, আমি এই জাতীয় কিছু করছিলাম:

while($. < $skipLines) {<FILE>};

এই সমস্যার কারণে, শর্তটি মিথ্যা ছিল কারণ লাইন কাউন্টারটি সঠিকভাবে রিসেট করা হয়নি। আমি জানি না এটি কোনও ত্রুটিযুক্ত বা সহজ কোড কিনা ... এছাড়াও close;ওডার কল করা close STDIN;কোনও লাভ করে না।

আমি এই অপঠনযোগ্য কোডটি ওপেন, স্ট্রিং কনকেন্টেশন এবং ক্লোজ ব্যবহার করে প্রতিস্থাপন করেছি। তবে ব্র্যাড গিলবার্ট পোস্ট করা সমাধানটিও কাজ করে যেহেতু এটির পরিবর্তে একটি সুস্পষ্ট ফাইল হ্যান্ডেল ব্যবহার করে।

শুরুতে তিনটি লাইন প্রতিস্থাপন করা যেতে পারে:

my $content = do{local $/; open(my $f1, '<', $filename) or die $!; my $tmp1 = <$f1>; close $f1 or die $!; $tmp1};
my $content2 = do{local $/; open(my $f2, '<', $filename) or die $!; my $tmp2 = <$f2>; close $f2 or die $!; $tmp2};
my $content3 = do{local $/; open(my $f3, '<', $filename) or die $!; my $tmp3 = <$f3>; close $f3 or die $!; $tmp3};

যা সঠিকভাবে ফাইল হ্যান্ডেলটি বন্ধ করে দেয়।


2

ব্যবহার

 $/ = undef;

আগে $document = <FILE>;$/হয় ইনপুট রেকর্ড বিভাজক , যা ডিফল্টভাবে একটি newline হয়। এটিকে নতুন করে সংজ্ঞায়িত করে আপনি undefবলছেন যে কোনও ফিল্ড বিভাজক নেই। একে "স্লুর্প" মোড বলা হয়।

অন্যান্য সমাধান যেমন undef $/এবং local $/(তবে নয় my $/) পুনরায় ঘোষিত $ / এবং এইভাবে একই প্রভাব উত্পাদন করে।



0

আমি জানি না এটি ভাল অনুশীলন কিনা, তবে আমি এটি ব্যবহার করতাম:

($a=<F>);

-1

এগুলি সব ভাল উত্তর। তবে আপনি যদি অলস বোধ করছেন এবং ফাইলটি এত বড় না, এবং সুরক্ষা কোনও সমস্যা নয় (আপনি জানেন যে আপনার কোনও কলঙ্কযুক্ত ফাইলের নাম নেই) তবে আপনি শেল আউট করতে পারেন:

$x=`cat /tmp/foo`;    # note backticks, qw"cat ..." also works

-2

আপনি লিনাক্সে বিড়াল ব্যবহার করতে পারেন:

@file1=\`cat /etc/file.txt\`;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.