Bu, Ubuntu Online, Fedora Online, Windows çevrimiçi öykünücüsü veya MAC OS çevrimiçi öykünücüsü gibi birden fazla ücretsiz çevrimiçi iş istasyonumuzdan birini kullanarak OnWorks ücretsiz barındırma sağlayıcısında çalıştırılabilen perlfaq5 komutudur.
Program:
ADI
perlfaq5 - Dosyalar ve Biçimler
VERSION
sürümü 5.021009
TANIM
Bu bölüm G/Ç ve "f" sorunları ile ilgilidir: kütük tanıtıcıları, temizleme, formatlar ve
altbilgiler.
Ne kadar do I temizle/arabelleği kaldır an çıktı kütük sapı? Neden Şimdi , eğer mülteci statüleri sona erdirilmemişse Amerika'ya geldikten bir yıl sonra I do bu?
(brian d foy'un katkılarıyla)
Mark Jason Dominus'un "Tamponlamadan Acı Çekmek" adlı kitabını şu adreste okumak isteyebilirsiniz:
<http://perl.plover.com/FAQs/Buffering.html>.
Perl normalde çıktıyı arabelleğe alır, böylece her çıktı biti için bir sistem çağrısı yapmaz. Tarafından
çıktıdan tasarruf ederek daha az maliyetli sistem araması yapar. Örneğin, bu küçük
kodu, izlemek için işlediğiniz her satır için ekrana bir nokta yazdırmak istiyorsunuz.
programınızın ilerlemesi. Her satır için bir nokta görmek yerine, Perl çıktıyı tamponlar
ve aynı anda 50 noktadan oluşan bir sıra görmeden önce uzun bir bekleyişiniz var:
# uzun süre bekle, sonra bir sıra nokta
süre( <> ) {
Yazdır ".";
++$count % 50 olmadıkça "\n" yazdır;
#... pahalı hat işleme operasyonları
}
Bunu aşmak için, bu durumda "STDOUT" olan çıktı kütük tanıtıcısının arabelleğini kaldırmanız gerekir.
$| özel değişkenini ayarlayabilirsiniz. gerçek bir değere (anımsatıcı: kütük tanıtıcılarınızı yapmak
"sıcak"):
$|++;
# nokta hemen gösteriliyor
süre( <> ) {
Yazdır ".";
++$count % 50 olmadıkça "\n" yazdır;
#... pahalı hat işleme operasyonları
}
$| kütükbelirteci başına özel değişkenlerden biridir, bu nedenle her kütükbelirteci kendi kopyasına sahiptir
onun değerinden. Örneğin standart çıktı ile standart hatayı birleştirmek istiyorsanız,
her birinin arabelleğini kaldırmanız gerekir (ancak STDERR varsayılan olarak arabelleğe alınmamış olabilir):
{
benim $previous_default = seç(STDOUT); # önceki varsayılanı kaydet
$|++; # otomatik yıkama STDOUT
seç(STDERR);
$|++; # emin olmak için STDERR'yi otomatik yıkayın
seç($önceki_default); # önceki varsayılanı geri yükle
}
# şimdi değişmeli . ve +
süre( 1 ) {
uyku 1;
STDOUT'u yazdır ".";
STDERR "+" yazdır;
++$count % 25 olmadıkça STDOUT "\n" yazdır;
}
$| yanında özel değişken, kütük tanıtıcınıza bir ":unix" vermek için "binmode" kullanabilirsiniz
arabelleğe alınmamış katman:
binmode(STDOUT, ":unix");
süre( 1 ) {
uyku 1;
Yazdır ".";
++$count % 50 olmadıkça "\n" yazdır;
}
Çıktı katmanları hakkında daha fazla bilgi için, "binmode" girişlerine bakın ve perlfunc'ta açın,
ve PerliIO modülü belgeleri.
IO::Handle veya alt sınıflarından birini kullanıyorsanız, "autoflush" yöntemini çağırabilirsiniz.
kütük tanıtıcısının ayarlarını değiştirmek için:
IO::Tutamak kullanın;
open my( $io_fh ), ">", "output.txt";
$io_fh->otomatik yıkama(1);
IO::Handle nesnelerinin ayrıca bir "flush" yöntemi vardır. Tamponu istediğiniz zaman temizleyebilirsiniz.
otomatik arabelleğe alma olmadan istiyorum
$io_fh->flush;
Ne kadar do I değişiklik, silme or eklemek a hat in a dosyası, or eklemek için the başlangıç of a dosya?
(brian d foy'un katkılarıyla)
Bir metin dosyasından satır ekleme, değiştirme veya silmenin temel fikri şunları içerir:
değişiklik yapmak istediğiniz noktaya kadar dosyayı okuyup yazdırmak, değişikliği yapmak,
sonra dosyanın geri kalanını okuyup yazdırın. Perl rastgele erişim sağlamaz
satırlar (özellikle kayıt giriş ayırıcısı $/ değiştirilebilir olduğundan), bu tür modüller
Tie::File olarak sahte olabilir.
Bu görevleri yapmak için bir Perl programı, bir dosyayı açmanın temel biçimini alır.
satırları, ardından dosyayı kapatın:
$in, '<', $file dosyamı aç veya öl "Eski dosya okunamıyor: $!";
$out, '>', "$file.new" dosyamı aç veya "Yeni dosya yazılamıyor: $!";
while( <$in> ) {
$ çıktı $_;
}
$out'u kapat;
Bu temel formun içine satır eklemeniz, değiştirmeniz veya silmeniz gereken parçaları ekleyin.
Satırları başa eklemek için, yazdırılan döngüye girmeden önce bu satırları yazdırın.
mevcut hatlar.
$in, '<', $file dosyamı aç veya öl "Eski dosya okunamıyor: $!";
$out, '>', "$file.new" dosyamı aç veya "Yeni dosya yazılamıyor: $!";
print $out "# Bu satırı en üste ekleyin\n"; # <--- İŞTE SİHİR
while( <$in> ) {
$ çıktı $_;
}
$out'u kapat;
Mevcut satırları değiştirmek için, "while" döngüsü içindeki satırları değiştirmek için kodu ekleyin. İçinde
bu durumda, kod "Perl"in tüm küçük harfli sürümlerini bulur ve onları büyük harf yapar. NS
her satırda olur, bu yüzden bunu her satırda yapmanız gerektiğinden emin olun!
$in, '<', $file dosyamı aç veya öl "Eski dosya okunamıyor: $!";
$out, '>', "$file.new" dosyamı aç veya "Yeni dosya yazılamıyor: $!";
print $out "# Bu satırı en üste ekleyin\n";
while( <$in> ) {
s/\b(Perl)\b/Perl/g;
$ çıktı $_;
}
$out'u kapat;
Yalnızca belirli bir satırı değiştirmek için, giriş satırı numarası $. kullanışlıdır. İlk okuma ve
satırları değiştirmek istediğinize kadar yazdırın. Ardından, istediğiniz tek satırı okuyun
değiştirin, değiştirin ve yazdırın. Bundan sonra, satırların geri kalanını okuyun ve şunları yazdırın:
while( <$in> ) { # değişiklikten önceki satırları yazdır
$ çıktı $_;
$ ise son. == 4; # değişiklikten önceki satır numarası
}
benim $line = <$in>;
$satır =~ s/\b(perl)\b/Perl/g;
$çıktı $satır;
while( <$in> ) { # satırların geri kalanını yazdır
$ çıktı $_;
}
Satırları atlamak için döngü kontrollerini kullanın. Bu örnekteki "sonraki", yorum satırlarını atlar,
ve "son", "__END__" veya "__DATA__" ile karşılaştığında tüm işlemleri durdurur.
while( <$in> ) {
sonraki if /^\s+#/; # yorum satırlarını atla
son if /^__(END|DATA)__$/; # kod işaretçisinin sonunda dur
$ çıktı $_;
}
Satırları atlamak için "ileri" düğmesini kullanarak belirli bir satırı silmek için aynı şeyi yapın
çıktıda görünmek istemezsiniz. Bu örnek her beşinci satırı atlar:
while( <$in> ) {
sonraki $ sürece. % 5;
$ çıktı $_;
}
Garip bir nedenden dolayı, tüm dosyayı bir kerede görmek yerine gerçekten görmek istiyorsanız,
satır satır işleyerek, içine slurp yapabilirsiniz (her şeyi içine sığdırabildiğiniz sürece
hafıza!):
$in, '<', $file dosyamı aç veya öl "Eski dosya okunamıyor: $!"
$out, '>', "$file.new" dosyamı aç veya "Yeni dosya yazılamıyor: $!";
benim $içeriğim = do { yerel $/; <$in> }; # slurp!
# sihrini burada yap
$çıktı $içerik;
Path::Tiny ve Tie::File gibi modüller de bu konuda yardımcı olabilir. Ancak yapabilirsen,
tüm dosyayı bir kerede okumaktan kaçının. Perl, bu belleği işletime geri vermeyecek
süreç bitene kadar sistem
Bir dosyayı yerinde değiştirmek için Perl tek gömleklerini de kullanabilirsiniz. Aşağıdakiler her şeyi değiştirir
'Fred'den 'Barney'e inFile.txt, yeni içeriği dosyanın üzerine yazar. İle
"-p" anahtarı, Perl "-e" ve "-i" ile belirttiğiniz kodun etrafına bir "while" döngüsü sarar
yerinde düzenlemeyi açar. Geçerli satır $_ içinde. "-p" ile Perl otomatik olarak yazdırır
döngünün sonundaki $_ değeri. Daha fazla ayrıntı için perlrun'a bakın.
perl -pi -e 's/Fred/Barney/' inFile.txt
"inFile.txt" dosyasının yedeğini almak için, "-i"ye eklemek üzere bir dosya uzantısı verin:
perl -pi.bak -e 's/Fred/Barney/' inFile.txt
Yalnızca beşinci satırı değiştirmek için, giriş satırı numarası olan bir test denetimi $. ekleyebilirsiniz, ardından
işlemi yalnızca test geçtiğinde gerçekleştirin:
perl -pi -e 's/Fred/Barney/ eğer $. == 5' inFile.txt
Belirli bir satırın önüne satır eklemek için, Perl $_ yazdırmadan önce bir satır (veya satır!) ekleyebilirsiniz:
perl -pi -e '$ ise "Üçüncü satırdan önce koy\n" yazdır. == 3' inFile.txt
Geçerli satır, dosyanın başına yazdırıldığından, dosyanın başına bir satır bile ekleyebilirsiniz.
döngünün sonu:
perl -pi -e '$ ise "İlk satırdan önce koy\n" yazdır. == 1' inFile.txt
Dosyada bulunan bir satırdan sonra bir satır eklemek için "-n" anahtarını kullanın. Tıpkı "-p" gibi
döngünün sonunda $_ yazmaması dışında, bunu kendiniz yapmanız gerekir.
Bu durumda, önce $_ yazdırın, ardından eklemek istediğiniz satırı yazdırın.
perl -ni -e 'yazdır; $ ise "Beşinci satırdan sonra koy\n" yazdır. == 5' inFile.txt
Satırları silmek için yalnızca istediklerinizi yazdırın.
perl -ni -e 'eğer /d/'yi yazdırın inFile.txt
Ne kadar do I saymak the numara of hatları in a dosya?
(brian d foy'un katkılarıyla)
Kavramsal olarak, bir dosyadaki satırları saymanın en kolay yolu, onları basitçe okumak ve
onları say:
benim $sayım = 0;
while( <$fh> ) { $count++; }
Perl zaten bunu
$. okunan son kütük tanıtıcısının geçerli satır numarası olan değişken:
1 süre( <$fh>);
benim $sayım = $.;
$. kullanmak istiyorsanız, aşağıdakilerden biri gibi basit bir tek satıra indirgeyebilirsiniz:
% perl -lne '} yazdır $.; {' dosya
% perl -lne 'END { yazdır $. }' dosya
Bunlar oldukça verimsiz olabilir. Sizin için yeterince hızlı değillerse,
veri parçalarını okuyun ve yeni satır sayısını sayın:
benim $satırlarım = 0;
open my($fh), '<:raw', $filename or die "$filename açılamıyor: $!";
while( sysread $fh, $tampon, 4096 ) {
$satır += ( $arabellek =~ tr/\n// );
}
yakın $fh;
Ancak, satır sonu yeni satır değilse bu çalışmaz. bunu değiştirebilirsin
"tr///" ile "s///" arasında giriş kayıt ayırıcısının kaç kez olduğunu sayabilirsiniz, $/,
ortaya çıkıyor:
benim $satırlarım = 0;
open my($fh), '<:raw', $filename or die "$filename açılamıyor: $!";
while( sysread $fh, $tampon, 4096 ) {
$satır += ( $tampon =~ s|$/||g; );
}
yakın $fh;
Dışarı atmaktan çekinmiyorsanız, "wc" komutu genellikle en hızlı komuttur.
ekstra süreçler arası ek yük. Yine de lekesiz bir dosya adınız olduğundan emin olun:
#!Perl -T
$ENV{YOL} = tanımsız;
benim $çizgilerim;
if( $dosyaadı =~ /^([0-9a-z_.]+)\z/ ) {
$satır = `/usr/bin/wc -1 dolar
$satırları parçala;
}
Ne kadar do I silmek the son N hatları itibaren a dosya?
(brian d foy'un katkılarıyla)
En kolay kavramsal çözüm, dosyadaki satırları saymak ve ardından
başlangıç ve satır sayısını (eksi son N) yeni bir dosyaya yazdırın.
Çoğu zaman asıl soru, daha fazlasını yapmadan son N satırını nasıl silebileceğinizdir.
dosya üzerinden birden fazla geçiş veya çok fazla kopyalama olmadan nasıl yapılacağı. kolay kavramdır
dosyanızda milyonlarca satırın olabileceği zor gerçek.
Bir püf noktası, dosyanın sonunda başlayan File::ReadBackwards kullanmaktır. o modül
hareket etmenizi kolaylaştırmak için gerçek kütükbelirteci saran bir nesne sağlar
dosya. İhtiyacınız olan noktaya vardığınızda, gerçek kütük tutacağını alabilir ve çalışabilirsiniz.
onunla normal olarak. Bu durumda dosya konumunu son satırın sonunda alırsınız.
dosyayı o noktaya kadar tutmak ve kısaltmak istiyorsanız:
File::ReadBackwards'ı kullanın;
$dosyaismim = 'test.txt';
benim $Lines_to_truncate = 2;
benim $bw = File::ReadBackwards->new( $filename )
or die "[$filename] içinde geriye doğru okunamadı: $!";
benim $lines_from_end = 0;
kadar( $bw->eof veya $lines_from_end == $Lines_to_truncate ) {
print "Got: ", $bw->readline;
$lines_from_end++;
}
truncate( $dosyaadı, $bw->tell );
File::ReadBackwards modülü ayrıca giriş kaydını ayarlama avantajına da sahiptir.
normal bir ifadeye ayırıcı.
Ayrıca, bağlı bir bağlantı aracılığıyla hatlara erişmenizi sağlayan Tie::File modülünü de kullanabilirsiniz.
dizi. Dosyanızı değiştirmek için normal dizi işlemlerini kullanabilirsiniz.
dizin ve "ekleme" kullanarak.
Ne kadar yapabilmek I kullanım Perl en "-BEN" seçenek itibaren içinde a program?
"-i" Perl'in $^I değişkeninin değerini ayarlar ve bu da "<>" davranışını etkiler;
daha fazla ayrıntı için perlrun'a bakın. Uygun değişkenleri doğrudan değiştirerek,
daha büyük bir program içinde aynı davranış. Örneğin:
#...
{
local($^I, @ARGV) = ('.orig', glob("*.c"));
süre (<>) {
eğer ($. == 1) {
print "Bu satır her dosyanın en üstünde görünmelidir\n";
}
s/\b(p)earl\b/${1}erl/i; # Doğru yazım hataları, büyük/küçük harf korunarak
baskı;
eof ise ARGV'yi kapatın; # $ sıfırla.
}
}
# $^I ve @ARGV burada eski değerlerine dönüyor
Bu blok, geçerli dizindeki tüm ".c" dosyalarını değiştirerek dizinin bir yedeğini bırakır.
yeni bir ".c.orig" dosyasındaki her dosyadan orijinal veriler.
Ne kadar yapabilmek I kopya a dosya?
(brian d foy'un katkılarıyla)
Dosya::Kopyala modülünü kullanın. Perl ile birlikte gelir ve dosya sistemleri arasında gerçek bir kopya yapabilir,
ve sihrini taşınabilir bir şekilde yapıyor.
Dosya::Kopyala'yı kullanın;
kopyala( $orijinal, $new_copy ) veya "Kopyalanamadı: $!";
File::Copy'yi kullanamıyorsanız, işi kendiniz yapmanız gerekir: orijinal dosyayı açın,
hedef dosyayı açın, ardından orijinali okurken hedef dosyaya yazdırın.
Ayrıca izinleri, sahibi ve grubu yeni dosyaya kopyalamayı da unutmamalısınız.
Ne kadar do I yapmak a geçici dosya isim?
Dosyanın adını bilmeniz gerekmiyorsa, "undef" yerine "open()" kullanabilirsiniz.
dosya adından. Perl 5.8 veya sonraki sürümlerde, "open()" işlevi anonim bir
geçici dosya:
$tmp'imi aç, '+>', undef veya die $!;
Aksi takdirde, File::Temp modülünü kullanabilirsiniz.
Dosya::Temp qw/ tempfile tempdir /;
benim $dir = tempdir(TEMİZLEME => 1 );
($fh, $dosyaadı) = tempfile( DIR => $dir );
# veya dosya adını bilmeniz gerekmiyorsa
benim $fh = tempfile(DIR => $dir);
File::Temp, Perl 5.6.1'den beri standart bir modül olmuştur. eğer modern değilsen
yeterli Perl kuruluysa, almak için IO::File modülünden "new_tmpfile" sınıf yöntemini kullanın.
okuma ve yazma için açılan bir kütük tanıtıcısı. Dosyayı bilmeniz gerekmiyorsa kullanın.
adı:
IO::Dosya kullanın;
benim $fh = IO::File->new_tmpfile()
veya "Yeni geçici dosya oluşturulamıyor: $!";
Elle geçici bir dosya oluşturmaya kararlıysanız, işlem kimliğini ve/veya
geçerli zaman değeri. Bir işlemde çok sayıda geçici dosyaya ihtiyacınız varsa, bir
tezgah:
BAŞLA {
Fcntl'yi kullanın;
Dosya::Spec;
benim $temp_dir = Dosya::Spec->tmpdir();
benim $file_base = sprintf "%d-%d-0000", $$, zaman;
benim $base_name = Dosya::Spec->catfile($temp_dir, $file_base);
alt temp_file {
benim $fh;
benim $sayım = 0;
kadar( tanımlı(fileno($fh)) || $say++ > 100 ) {
$taban_adı =~ s/-(\d+)$/"-" . (1 + $1)/e;
# O_EXCL güvenlik nedeniyle gereklidir.
sysopen $fh, $base_name, O_WRONLY|O_EXCL|O_CREAT;
}
if( tanımlı fileno($fh) ) {
dönüş ($fh, $taban_adı);
}
else {
dönüş ();
}
}
}
Ne kadar yapabilmek I manipüle sabit kayıt uzunluğu dosyalar?
En verimli yol kullanmaktır ambalaj() ve paketini aç(). Bu kullanmaktan daha hızlı alt dizi ()
çok, çok sayıda dize alırken. Sadece birkaçı için daha yavaştır.
İşte bazı sabit formatları parçalamak ve tekrar bir araya getirmek için örnek bir kod yığını
giriş satırları, bu durumda normal, Berkeley tarzı bir ps çıktısından:
# örnek giriş satırı:
# 15158 p5 T 0:00 perl /home/tchrist/scripts/şimdi-ne
benim $PS_T = 'A6 A4 A7 A5 A*';
$ps'ımı aç, '-|', 'ps';
skaler yazdır <$ps>;
@alanlarım = qw( pid tt stat zaman komutu);
while (<$ps>) {
benim % işlemim;
@process{@fields} = paketi aç($PS_T, $_);
$alanım için ( @fields ) {
print "$alan: <$işlem{$alan}>\n";
}
print 'line=', pack($PS_T, @process{@fields} ), "\n";
}
Her satırın alanlarını kolayca işlemek için bir karma dilim kullandık. saklamak
Bir dizideki anahtarlar, üzerlerinde bir grup olarak çalışmayı veya "for" ile üzerlerinde dolaşmayı kolaylaştırır.
Ayrıca programı global değişkenlerle kirletmekten ve sembolik referanslar kullanmaktan kaçınır.
Ne kadar yapabilmek I yapmak a eğe sapı yerel için a alt program? Ne kadar do I geçmek eğe sapları arasında
alt programlar? Ne kadar do I yapmak an dizi of kütük tutacağı?
Perl5.6'dan itibaren, açık() dosya ve dizin tanıtıcılarını, geçerseniz referans olarak otomatik olarak canlandırır
başlatılmamış bir skaler değişken. Daha sonra bu referansları tıpkı diğerleri gibi iletebilirsiniz.
skaler ve bunları adlandırılmış tutamaçların yerine kullanın.
$fh, $file_name'imi aç;
yerel $fh, $dosya_adı açın;
print $fh "Merhaba Dünya!\n";
process_file($fh);
İsterseniz, bu kütük tanıtıcılarını bir dizide veya bir karmada saklayabilirsiniz. onlara erişirseniz
doğrudan, basit skaler değiller ve yerleştirerek "baskıya" biraz yardım etmeniz gerekiyor.
parantez içindeki kütükbelirteci referansı. Perl bunu ancak
filehandle referansı basit bir skalerdir.
benim @fhs = ( $fh1, $fh2, $fh3);
for( $i = 0; $i <= $#fhs; $i++ ) {
print {$fhs[$i]} "sadece başka bir Perl yanıtı, \n";
}
Perl5.6'dan önce, daha eski sürümlerde görebileceğiniz çeşitli typeglob deyimleriyle uğraşmak zorundaydınız.
kodu.
DOSYA'yı açın, "> $dosyaadı";
process_typeglob(*DOSYA);
process_reference( \*DOSYA);
sub process_typeglob { local *FH = shift; FH "Typeglob!" yazdır }
sub process_reference { local $fh = shift; print $fh "Referans!" }
Çok sayıda isimsiz tanıtıcı oluşturmak istiyorsanız, Sembolü kontrol etmelisiniz veya
IO::Modülleri yönetin.
Ne kadar yapabilmek I kullanım a eğe sapı dolaylı olarak?
Dolaylı bir kütük tanıtıcı, bir yerde bir sembolden başka bir şeyin kullanılmasıdır.
filehandle bekleniyor. Dolaylı kütük tanıtıcıları almanın yolları şunlardır:
$fh = SOME_FH; # bareword katı abone düşmanlığıdır
$fh = "BAZI_FH"; # katı hakemler düşmanca; sadece aynı paket
$fh = *BAZI_FH; # yazı glob'u
$fh = \*SOME_FH; # typeglob'a başvuru (bless-güçlü)
$fh = *SOME_FH{IO}; # kutsanmış IO:: *SOME_FH typeglob'dan tut
Veya bir anonim oluşturmak için IO::* modüllerinden birindeki "yeni" yöntemi kullanabilirsiniz.
filehandle ve bunu bir skaler değişkende saklayın.
IO::Tutamak kullanın; # 5.004 veya üzeri
benim $fh = IO::Handle->new();
Ardından, normal bir kütük tanıtıcısı gibi bunlardan herhangi birini kullanın. Perl'in beklediği her yerde
kütükbelirteci, bunun yerine dolaylı bir kütükbelirteci kullanılabilir. Dolaylı bir kütük tanıtıcısı sadece bir
kütükbelirteci içeren skaler değişken. "Yazdır", "aç", "ara" gibi işlevler veya
" " elmas operatörü, adlandırılmış bir kütükbelirteci veya bir skaler değişkeni kabul edecektir.
birini içeren:
($ifh, $ofh, $efh) = (*STDIN, *STDOUT, *STDERR);
print $ofh "Yazın: ";
benim $aldım = <$ifh>
print $efh "Bu neydi: $var";
Bir işleve kütük tanıtıcısı iletiyorsanız, işlevi iki şekilde yazabilirsiniz:
alt kabul_fh {
benim $fh = vardiyam;
print $fh "Dolaylı dosya tanıtıcısına gönderiliyor\n";
}
Veya bir typeglob'u yerelleştirebilir ve kütük tanıtıcısını doğrudan kullanabilir:
alt kabul_fh {
yerel *FH = kaydırma;
print FH "Yerelleştirilmiş kütüğe gönderiliyor\n";
}
Her iki stil de gerçek kütükbelirteçlerinin nesneleriyle veya tip küreleriyle çalışır. (Onlar da olabilir
bazı durumlarda dizelerle çalışın, ancak bu risklidir.)
kabul_fh(*STDOUT);
kabul_fh($işle);
Yukarıdaki örneklerde, kütükbelirteci kullanmadan önce bir skaler değişkene atadık.
Bunun nedeni, yalnızca basit skaler değişkenlerin, karmaların ifadeleri veya alt simgelerinin olmamasıdır.
diziler, "print", "printf" veya elmas operatörü gibi yerleşiklerle kullanılabilir. kullanma
kütükbelirteci olarak basit bir skaler değişkenden başka bir şey yasa dışıdır ve hatta
derlemek:
benim @fd = (*STDIN, *STDOUT, *STDERR);
print $fd[1] "Yazın: "; # YANLIŞ
benim $get = <$fd[0]> # YANLIŞ
print $fd[2] "Bu neydi: $var"; # YANLIŞ
"print" ve "printf" ile, bir blok ve bir ifade kullanarak bu sorunu çözebilirsiniz.
dosya tanıtıcısını yerleştirirsiniz:
print { $fd[1] } "komik şeyler\n";
printf { $fd[1] } "Zavallı %x'e yazık.\n", 3_735_928_559;
# Zavallı ölü bifteğe acı.
Bu blok, diğerleri gibi uygun bir bloktur, böylece oraya daha karmaşık kodlar koyabilirsiniz.
Bu, mesajı iki yerden birine gönderir:
benim $tamam = -x "/bin/kedi";
yazdır { $tamam mı? $fd[1] : $fd[2] } "kedi istatistiği $tamam\n";
print { $fd[ 1+ ($tamam || 0) ] } "cat stat $tamam\n";
"print" ve "printf" benzeri nesne yöntemleri çağrılarını ele alma yaklaşımı şu durumlarda işe yaramaz:
elmas operatörü. Bunun nedeni, bunun gerçek bir operatör olması, yalnızca
virgülsüz argüman. Bizim yaptığımız gibi typeglob'ları yapınızda sakladığınızı varsayarsak
yukarıda, bir kaydı "<>" gibi okumak için "readline" adlı yerleşik işlevi kullanabilirsiniz.
yapmak. @fd için yukarıda gösterilen başlatma göz önüne alındığında, bu işe yarar, ancak yalnızca
okuma satırı() typeglob gerektirir. olabilecek nesneler veya dizelerle çalışmaz.
henüz düzeltmediğimiz hata.
$got = satır oku($fd[0]);
Dolaylı kütükbelirteçlerinin pul pul olmasının aşağıdakilerle ilgili olmadığı belirtilmelidir.
bunlar diziler, typeglob'lar, nesneler veya başka herhangi bir şeydir. Bu, temelin sözdizimidir
operatörler. Nesne oyununu oynamak burada size hiç yardımcı olmuyor.
Ne kadar yapabilmek I set up a altbilgi biçim için be Kullanılmış ile yazmak()?
Bunu yapmanın yerleşik bir yolu yoktur, ancak perlform'un bunu yapmak için birkaç tekniği vardır.
cesur hacker için mümkün.
Ne kadar yapabilmek I yazmak() içine a dize?
(brian d foy'un katkılarıyla)
Bir dizgeye "yazmak" istiyorsanız, yapmanız gereken tek şey bir dizgeye bir kütük tanıtıcısı,
hangi Perl, Perl 5.6'dan beri yapabilmektedir:
FH, '>', \my $string;
yaz (FH);
İyi bir programcı olmak istediğinize göre, muhtemelen sözcüksel bir kütük tanıtıcısı kullanmak istersiniz,
biçimler, varsayılandan beri çıplak sözcük dosya tanıtıcılarıyla çalışmak üzere tasarlanmış olsa da
biçim adları kütük tanıtıcı adını alır. Ancak, bunu bazı Perl ile kontrol edebilirsiniz.
dosya tanıtıcısı başına özel değişkenler: sayfanın üstü biçimini adlandıran $^ ve
çizgi biçimini gösterir. Bu değişkenleri ayarlamak için varsayılan kütük tanıtıcısını değiştirmeniz gerekir:
open my($fh), '>', \my $string;
{ # kütükbelirteci başına değişkenleri ayarla
benim $old_fh = seç( $fh );
$~ = 'HAYVAN';
$^ = 'ANIMAL_TOP';
seç($eski_fh);
}
ANIMAL_TOP biçimi =
Kimlik Türü Adı
.
biçim HAYVAN =
@## @<<< @<<<<<<<<<<<<<
$kimlik, $tür, $ad
.
Yazma, sözcüksel veya paket değişkenlerle çalışabilse de, kullandığınız değişkenler ne olursa olsun
formatında kapsamak için. Bu büyük olasılıkla bazı paketleri yerelleştirmek isteyeceğiniz anlamına gelir.
değişkenleri:
{
local( $id, $type, $name ) = qw( 12 cat Buster );
yaz($fh);
}
$dize yazdır;
Ayrıca "formline" ve akümülatör değişkeni ile oynayabileceğiniz bazı püf noktaları da var.
$^A, ancak "formline" sayfalamayı işlemeyeceğinden biçimlerin değerini kaybedersiniz ve
yakın zamanda. Formatları kullandığınızda onları yeniden uygularsınız.
Ne kadar yapabilmek I açık a eğe sapı için a dize?
(Peter J. Holzer tarafından katkıda bulunulmuştur, [e-posta korumalı])
Perl 5.8.0'dan beri, bir dizgeye atıfta bulunan bir dosya tanıtıcısı ile open çağrılarak oluşturulabilir.
dosya adı yerine bu dizeye başvuru. Bu dosya tanıtıcısı daha sonra
dizeden oku veya dizeye yaz:
open(my $fh, '>', \$string) or die "Dize yazmak için açılamadı";
$fh "foo\n" yazdır;
$fh "bar\n" yazdır; # $string artık "foo\nbar\n" içeriyor
open(my $fh, '<', \$string) or die "Dize okumak için açılamadı";
benim $x = <$fh>; # $x artık "foo\n" içeriyor
Perl'in eski sürümleriyle, IO::String modülü benzer işlevsellik sağlar.
Ne kadar yapabilmek I çıktı my sayılar ile virgül katma?
(brian d foy ve Benjamin Goldberg tarafından katkıda bulunulmuştur)
Bir sayıdaki yerleri ayırmak için Number::Format'ı kullanabilirsiniz. Yerel ayar bilgilerini işler
bunun yerine nokta eklemek isteyenler için (veya istedikleri başka bir şey)
kullanın, gerçekten).
Bu alt program numaranıza virgül ekleyecektir:
alt iletişim {
yerel $_ = vardiya;
1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
$_ döndür;
}
Benjamin Goldberg'den gelen bu normal ifade, sayılara virgül ekleyecektir:
s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d) )/1$/g;
Yorumlarla görmek daha kolay:
S/(
^[-+]? # sayının başlangıcı.
\d+? # ilk virgülden önceki ilk basamak
(?= # ardından, (ama maça dahil değil):
(?>(?:\d{3})+) # üç rakamın bir pozitif katı.
(?!\d) # bir *tam* kat, x * 3 + 1 veya her neyse.
)
| # veya:
\G\d{3} # son gruptan sonra üç hane alın
(?=\d) # ama arkalarında daha fazla rakam olması gerekiyor.
)/1$/xg;
Ne kadar yapabilmek I çevirmek yaklaşık işareti (~) in a dosya adı?
perlfunc'ta belgelenmiş <> ("glob()") operatörünü kullanın. Perl'in 5.6'dan eski sürümleri
tildes yapan bir kabuğun kurulu olmasını gerektirir. Perl'in sonraki sürümlerinde
bu özellik yerleşiktir. File::KGlob modülü (CPAN'dan edinilebilir) daha taşınabilir
küre işlevselliği.
Perl içinde bunu doğrudan kullanabilirsiniz:
$dosyaadı =~ s{
^ ~ # önde gelen bir tilde bul
( # bunu $1'a kaydet
[^/] # eğik çizgi olmayan bir karakter
* # 0 veya daha fazla kez tekrarlandı (0 beni ifade ediyor)
)
}{
$1
? (getpwnam($1))[7]
: ( $ENV{HOME} || $ENV{LOGDIR} )
}eski;
Ne kadar nasıl ne zaman I açık a dosya salt yazma it mendil it dışarı?
Çünkü dosyayı kesen böyle bir şey kullanıyorsunuz. sonra okumanı sağlar-
yazma erişimi:
$fh, '+>', '/path/name'; # YANLIŞ (neredeyse her zaman)
Vay canına. Bunun yerine, dosya yoksa başarısız olacak olan bunu kullanmalısınız:
$fh, '+<', '/path/name'; # güncelleme için aç
">" kullanmak her zaman engeller veya yaratır. "<" kullanmak da hiçbir zaman yapmaz. "+" değişmiyor
bu.
İşte birçok dosya açma türü örnekleri. "Sysopen" kullananların tümü şunu varsayıyor:
Fcntl'den sabitleri çektiniz:
Fcntl'yi kullanın;
Dosyayı okumak üzere açmak için:
$fh, '<', $path'ımı aç veya $ öl!;
sysopen benim $fh, $path, O_RDONLY veya die $!;
Dosyayı yazmak üzere açmak için gerekirse yeni dosya oluşturun veya eski dosyayı kısaltın:
$fh, '>', $path'ımı aç veya $ öl!;
sysopen benim $fh, $path, O_WRONLY|O_TRUNC|O_CREAT veya öl $!;
sysopen benim $fh, $path, O_WRONLY|O_TRUNC|O_CREAT, 0666 veya die $!;
Dosyayı yazmak üzere açmak için yeni dosya oluşturun, dosyanın olmaması gerekir:
sysopen benim $fh, $path, O_WRONLY|O_EXCL|O_CREAT veya die $!;
sysopen benim $fh, $path, O_WRONLY|O_EXCL|O_CREAT, 0666 veya die $!;
Dosyayı eklemek üzere açmak için gerekirse oluşturun:
$fh, '>>' $yolumu aç veya $ öl!;
sysopen benim $fh, $path, O_WRONLY|O_APPEND|O_CREAT veya öl $!;
sysopen benim $fh, $path, O_WRONLY|O_APPEND|O_CREAT, 0666 veya die $!;
Dosyayı eklemek üzere açmak için dosyanın mevcut olması gerekir:
sysopen benim $fh, $path, O_WRONLY|O_APPEND veya die $!;
Güncelleme için dosyayı açmak için dosyanın mevcut olması gerekir:
$fh, '+<', $path'ımı aç veya $ öl!;
sysopen benim $fh, $path, O_RDWR veya die $!;
Güncelleme için dosyayı açmak için gerekirse dosya oluşturun:
sysopen benim $fh, $path, O_RDWR|O_CREAT veya die $!;
sysopen benim $fh, $path, O_RDWR|O_CREAT, 0666 veya die $!;
Güncelleme için dosyayı açmak için dosyanın mevcut olmaması gerekir:
sysopen benim $fh, $path, O_RDWR|O_EXCL|O_CREAT veya die $!;
sysopen benim $fh, $path, O_RDWR|O_EXCL|O_CREAT, 0666 veya die $!;
Bir dosyayı engellemeden açmak için gerekirse oluşturun:
sysopen benim $fh, '/foo/somefile', O_WRONLY|O_NDELAY|O_CREAT
veya öl "/foo/somefile: $ açılamıyor!":
Ne dosya oluşturmanın ne de silmenin atomik olarak garanti edilmediği konusunda uyarılırsınız.
NFS üzerinden işlem. Diğer bir deyişle, iki süreç hem başarıyla oluşturabilir hem de bağlantısını kaldırabilir.
aynı dosya! Bu nedenle O_EXCL istediğiniz kadar özel değildir.
Ayrıca bkz.
Neden Şimdi do I bazen almak an "Argüman liste çok uzun" ne zaman I kullanım <*>?
"<>" operatörü bir küreselleştirme işlemi gerçekleştirir (yukarıya bakın). Daha önceki Perl sürümlerinde
v5.6.0'dan daha fazla dahili küre () operatör çatalları csh(1) gerçek küre genişlemesini yapmak için,
ancak csh 127'den fazla öğeyi işleyemez ve bu nedenle "Argüman listesi de
uzun". tcsh'ı csh olarak yükleyen kişiler bu sorunu yaşamazlar, ancak kullanıcıları
buna şaşırdı.
Bunu aşmak için, Perl v5.6.0 veya sonraki bir sürümüne yükseltin, küreyi kendiniz yapın
oku() ve kalıpları kullanın veya Shell'i kullanmayan File::Glob gibi bir modül kullanın.
küre yapmak.
Ne kadar yapabilmek I açık a dosya ile a önemli ">" or sondaki boşluklar?
(Brian McCauley'nin katkılarıyla)
Perl'in özel iki argüman formu açık() işlev, sondaki boşlukları yok sayar
dosya adlarını adlandırır ve modu belirli baştaki karakterlerden (veya sondaki bir "|") çıkarır. İçinde
Perl'in eski sürümleri bu, Perl'in tek sürümüydü. açık() ve bu yüzden eskilerde yaygındır
kod ve kitaplar.
İki argümanlı formu kullanmak için özel bir nedeniniz yoksa, üç argümanlı formu kullanmalısınız.
argüman formu açık() bu, dosya adındaki hiçbir karakteri özel olarak değerlendirmez.
$fh, "<", " dosyamı aç "; # dosya adı " dosya "
$fh, ">", ">file" dosyamı aç; # dosya adı ">dosya"
Ne kadar yapabilmek I güvenilir adını değiştirmek a dosya?
İşletim sisteminiz uygun bir mv(1) fayda veya işlevsel eşdeğeri,
bu çalışıyor:
rename($eski, $yeni) veya system("mv", $eski, $yeni);
Bunun yerine File::Copy modülünü kullanmak daha taşınabilir olabilir. sen sadece yenisine kopyala
dosyaya yeni bir ad verin (dönüş değerlerini kontrol edin), ardından eskisini silin. bu gerçekten değil
izinler gibi meta bilgileri koruyan "rename()" ile anlamsal olarak aynı,
zaman damgaları, düğüm bilgileri vb.
Ne kadar yapabilmek I kilitlemek a dosya?
Perl yerleşik sürü() işlev (ayrıntılar için perlfunc'a bakın) arayacak sürü(2) eğer öyleyse
, mevcut fcntl(2) değilse (Perl 5.004 ve sonraki sürümlerde) ve kilit(3) eğer hiçbiri
önceki iki sistem çağrısından biri mevcut. Hatta bazı sistemlerde farklı bir
yerel kilitleme şekli. İşte Perl's ile bazı yakalamalar sürü():
1. Üç sistemden hiçbiri (veya bunların yakın eşdeğeri) çağrılmazsa önemli bir hata üretir.
bulunmaktadır.
2. kilit(3) paylaşılan kilitleme sağlamaz ve kütük tanıtıcısının açık olmasını gerektirir.
yazma (veya ekleme veya okuma/yazma).
3. Bazı sürümleri sürü() dosyaları bir ağ üzerinden kilitleyemez (örn. NFS dosya sistemlerinde),
bu yüzden kullanımını zorlamanız gerekir fcntl(2) Perl oluşturduğunuzda. Ama bu bile
en iyi ihtimalle şüpheli. perlfunc'un sürü girişine bakın ve INSTALL kaynaktaki dosya
Bunu yapmak için Perl oluşturma hakkında bilgi için dağıtım.
İki potansiyel olarak açık olmayan ancak geleneksel sürü anlambilimi, beklemesidir.
kilit verilene ve kilitleri verilene kadar süresiz olarak sadece danışma. Böyle
isteğe bağlı kilitler daha esnektir, ancak daha az garanti sunar. Bunun anlamı şudur ki
ile kilitlenen dosyalar sürü() kullanmayan programlar tarafından değiştirilebilir. sürü().
Kırmızı ışıkta duran arabalar birbirleriyle iyi geçinirler, ancak kırmızı ışıkta duran arabalarla değil.
kırmızı ışıklar için durma. Bağlantı noktanıza özel olan perlport kılavuz sayfasına bakın
ayrıntılar için belgelere veya sisteminize özel yerel kılavuz sayfalarınıza bakın. varsaymak en iyisidir
taşınabilir programlar yazıyorsanız geleneksel davranış. (Eğer değilsen, yapmalısın
her zaman olduğu gibi, kendi sisteminizin kendine özgü özellikleri için yazmaktan çekinmeyin (bazen
"özellikler" olarak adlandırılır). Taşınabilirlik endişelerine kölece bağlılık, işin içine girmemelidir.
işinizi yapmanın yolu.)
Dosya kilitleme hakkında daha fazla bilgi için perlopentut'taki "Dosya Kilitleme" konusuna da bakın.
sahip olun (5.6 için yeni).
Neden Şimdi olamaz I sadece açık (FH, ">dosya.kilidi")?
Ortak bir kod parçası DEĞİL TO KULLANIMI şudur:
uyku(3) while -e 'dosya.lock'; # LÜTFEN KULLANMAYIN
$lock, '>', 'file.lock'; # BU BOZUK KOD
Bu klasik bir yarış koşuludur: yapılması gereken bir şeyi yapmak için iki adım atarsınız.
bir. Bu nedenle bilgisayar donanımı atomik bir test ve ayarla talimatı sağlar. Teoride,
bu "işe yaramalı":
sysopen benim $fh, "file.lock", O_WRONLY|O_EXCL|O_CREAT
veya die "file.lock'u açamıyor: $!";
bunun dışında, üzücü bir şekilde, dosya oluşturma (ve silme) NFS üzerinde atomik değildir, bu yüzden bu olmaz
(en azından, her zaman değil) ağ üzerinden çalışın. içeren çeşitli şemalar bağlantı() olmuştur
önerilir, ancak bunlar aynı zamanda arzu edilenden daha az olan meşgul beklemeyi içerir.
I yine de değil mi almak kilitleme. I sadece istemek için artım the numara in the dosyası. Ne kadar yapabilmek I do bu?
Hiç kimse size web sayfası hit sayaçlarının işe yaramaz olduğunu söylemedi mi? sayı saymıyorlar
hitler, zaman kaybıdır ve sadece yazarın kibirini okşamaya hizmet ederler. Onun
rastgele bir sayı seçmek daha iyidir; onlar daha gerçekçi.
Her neyse, kendine yardım edemezsen yapabileceğin şey bu.
Fcntl qw(:DEFAULT :flock) kullanın;
sysopen benim $fh, "numfile", O_RDWR|O_CREAT veya die "numfile açamıyor: $!";
flock $fh, LOCK_EX veya die "numfile: $ flock edemez!";
benim $sayı = <$fh> || 0;
$fh, 0, 0 veya die "numfile: $ geri sarılamaz!";
$fh, 0 veya die "numfile: $ kesilemiyor!";
(print $fh $num+1, "\n") veya die "numfile: $ yazamıyor!";
$fh'yi kapatın veya öl "numfile: $ kapatılamıyor!";
İşte çok daha iyi bir web sayfası isabet sayacı:
$hits = int( (zaman() - 850_000_000) / tüm(1_000) );
Sayı arkadaşlarınızı etkilemiyorsa, kod etkilenebilir. :-)
Tüm Posterler I istemek için do is eklemek a küçük miktar of metin için the son of a dosyası. Do I yine de var için kullanım
kilitleme?
"Flock" uygulamasını doğru şekilde uygulayan bir sistemdeyseniz ve ekleme örneğini kullanıyorsanız
"perldoc -f flock" kodu, üzerinde bulunduğunuz işletim sistemi olmasa bile her şey yoluna girecek
ekleme modunu doğru şekilde uygulayın (böyle bir sistem varsa). Yani kısıtlamaktan memnunsanız
kendinizi "sürü" uygulayan işletim sistemlerine (ve bu gerçekten bir kısıtlama değil)
yapman gereken bu.
Biliyorsanız, yalnızca eklemeyi doğru şekilde uygulayan bir sistem kullanacaksınız.
(yani Win32 değil) o zaman önceki cevaptaki koddan "aramayı" atlayabilirsiniz.
Yalnızca uygulayan bir işletim sistemi ve dosya sisteminde çalıştırmak için kod yazdığınızı biliyorsanız
modu doğru şekilde ekle (örneğin modern bir Unix'te yerel bir dosya sistemi) ve
blok arabellekli modda dosya ve her biri arasında çıktıyla dolu birden fazla arabellek yazıyorsunuz
arabelleğin manuel olarak yıkanması, ardından her bir arabellek yükünün yazılması neredeyse garanti edilir
dosyanın sonu, başka birinin çıktısıyla karışmadan bir yığın halinde.
Ayrıca sisteminizin etrafını saran "syswrite" işlevini de kullanabilirsiniz.
yazmak(2) sistem çağrısı.
Bir sinyalin sistem düzeyinde kesintiye uğraması için hala küçük bir teorik şans var.
tamamlanmadan önce "write()" işlemi. Ayrıca bazı STDIO'ların
uygulamalar, arabellek boş olsa bile, birden çok sistem düzeyi "write()" çağırabilir.
Başlat. Bu olasılığın sıfıra indirildiği bazı sistemler olabilir ve bu
sisteminizin STDIO'su yerine ":perlio" kullanırken endişe etmeyin.
Ne kadar do I rastgele güncelleştirme a ikili dosya?
Yalnızca bir ikili dosyayı yamalamaya çalışıyorsanız, çoğu durumda bu kadar basit bir şey işe yarar:
perl -i -pe 's{pencere yöneticisi}{pencere yöneticisi}g' /usr/bin/emacs
Ancak, sabit boyutlu kayıtlarınız varsa, bunun gibi bir şey daha yapabilirsiniz:
benim $RECSIZE = 220; # bayt cinsinden kayıt boyutu
benim $rekno = 37; # hangi kayıt güncellenecek
$fh, '+<', 'bir yerde' veya öl "bir yerde güncellenemiyor: $!";
$fh, $recno ara * $RECSIZE, 0;
okuma $fh, $rekor, $RECSIZE == $RECSIZE or die "$recno kaydı okunamıyor: $!";
# rekoru kır
$fh, -$RECSIZE, 1 ara;
$fh $kayıt yazdır;
yakın $fh;
Kilitleme ve hata kontrolü okuyucuya alıştırma olarak bırakılmıştır. bunları unutma ya
oldukça pişman olacaksın.
Ne kadar do I almak a Dosyalar zaman damgası in perl mi?
Dosyanın en son okunduğu, yazıldığı veya bulunduğu zamanı almak istiyorsanız
meta-veri (sahip, vb) değişti, -A, -Mya da -C olarak dosya test işlemleri
perfunc'ta belgelenmiştir. Bunlar dosyanın yaşını alır (başlangıca göre ölçülür)
programınızın zamanı) gün cinsinden kayan noktalı bir sayı olarak. Bazı platformlarda hepsi olmayabilir
bu zamanların. Ayrıntılar için perlport'a bakın. "ham" zamanı saniye cinsinden almak için
epoch, stat işlevini çağırır, ardından "localtime()", "gmtime()" veya
Bunu insan tarafından okunabilir forma dönüştürmek için "POSIX::strftime()".
İşte bir örnek:
benim $write_secs = (stat($dosya))[9];
printf "dosya %s, %s\n'de güncellendi", $file,
skaler yerel zaman($write_sec);
Daha okunaklı bir şey tercih ederseniz, File::stat modülünü kullanın (standartın bir parçası).
5.004 ve sonraki sürümlerde dağıtım):
# hata denetimi, okuyucu için bir alıştırma olarak kaldı.
Dosya::stat;
Time::localtime'ı kullanın;
benim $date_string = ctime(stat($file)->mtime);
print "file $file $date_string'de güncellendi\n";
The POSIX::strftime() yaklaşımın teoride bağımsız olma avantajına sahiptir.
geçerli yerel ayar. Ayrıntılar için perllocale'e bakın.
Ne kadar do I set a Dosyalar zaman damgası in perl mi?
Sen kullan zaman() perlfunc'ta "utime" içinde belgelenen işlev. Örnek olarak, burada
ilk argümanından tüm okuma ve yazma sürelerini kopyalayan küçük bir program
geri kalanı.
if (@ARGV < 2) {
die "kullanım: cptimes timestamp_file other_files ...\n";
}
$zaman damgam = vardiya;
my($atime, $mtime) = (stat($timestamp))[8,9];
utime $atime, $mtime, @ARGV;
Hata denetimi, her zamanki gibi okuyucuya bir alıştırma olarak bırakılmıştır.
utime için perldoc da aynı etkiye sahip bir örneğe sahiptir. dokunma(1) dosyalarda
o zaten mevcut.
Belirli dosya sistemleri, süreleri bir dosyada beklenen zamanda saklama konusunda sınırlı bir yeteneğe sahiptir.
hassasiyet seviyesi. Örneğin, FAT ve HPFS dosya sistemi şu tarihlerde tarih oluşturamaz:
iki saniyeden daha iyi bir ayrıntı düzeyine sahip dosyalar. Bu, dosya sistemlerinin bir sınırlamasıdır,
Değil zaman().
Ne kadar do I baskı için Daha göre bir dosya at bir Zamanlar?
Bir kütük tanıtıcıyı birkaç çıktı kütük tanıtıcısına bağlamak için, IO::Tee veya
Tie::FileHandle::Multiplex modülleri.
Bunu yalnızca bir kez yapmanız gerekiyorsa, her bir kütük sapına ayrı ayrı yazdırabilirsiniz.
benim $fh için ($fh1, $fh2, $fh3) { print $fh "ne olursa olsun\n" }
Ne kadar yapabilmek I okumak in an tüm dosya herşey at bir Zamanlar?
Bir dosyadaki tüm satırları işlemek için geleneksel Perl yaklaşımı, bunu bir satırda bir satır yapmaktır.
bir zaman:
$input, '<', $file veya die "$file dosyasını açamıyor: $!";
while (<$input>) {
lokma;
# $_ ile bir şeyler yap
}
$input'u kapat veya öl "$file kapatılamıyor: $!";
Bu, tüm dosyayı bir dizi olarak belleğe okumaktan çok daha verimlidir.
satırların ve ardından her seferinde bir öğenin işlenmesi, bu genellikle - neredeyse değilse bile
her zaman--yanlış yaklaşım. Ne zaman birini görsen şunu yapar:
@çizgilerim = ;
Neden her şeyin aynı anda yüklenmesi gerektiğini uzun uzun düşünmelisiniz. sadece değil
ölçeklenebilir bir çözüm.
Dosyayı CPAN'dan File::Map modülüyle "mmap" yaparsanız, dosyayı sanal olarak yükleyebilirsiniz.
tüm dosyayı gerçekten bellekte saklamadan bir dizgeye dönüştürün:
Dosya::Haritayı kullan qw(harita_dosyası);
map_file benim $dizgem, $dosyaadı;
Eşlendikten sonra, $string'i diğer dizelere yaptığınız gibi değerlendirebilirsiniz. yapmadığından beri
mutlaka verileri yüklemeniz gerekir, mmap-ing çok hızlı olabilir ve
bellek ayak izi
Ayrıca standart Tie::File modülünü veya DB_File'ı kullanmayı daha eğlenceli bulabilirsiniz.
modülün $DB_RECNO bağlamaları, bir diziyi bir dosyaya bağlamanıza izin verir, böylece erişim
dizinin bir elemanı aslında dosyadaki karşılık gelen satıra erişir.
Dosyanın tamamını yüklemek istiyorsanız, bunu tek bir dosyada yapmak için Path::Tiny modülünü kullanabilirsiniz.
basit ve verimli adım:
Path::Tiny'yi kullanın;
benim $all_of_it = path($filename)->slurp; # tüm dosya skaler olarak
@all_lines = path($filename)->lines; # öğe başına bir satır
Veya tüm dosya içeriğini aşağıdaki gibi bir skalere okuyabilirsiniz:
benim $varım;
{
yerel $/;
$fh, '<', $file dosyamı aç veya "$file dosyasını açamıyor: $!";
$var = <$fh>;
}
Bu, kayıt ayırıcınızı geçici olarak kaldırır ve dosyayı otomatik olarak kapatacaktır.
blok çıkışı. Dosya zaten açıksa, şunu kullanın:
benim $var = do { yerel $/; <$fh> };
"Açık" durumunu ortadan kaldırmak için yerelleştirilmiş bir @ARGV de kullanabilirsiniz:
benim $var = do { local( @ARGV, $/ ) = $dosya; <> };
Sıradan dosyalar için "oku" işlevini de kullanabilirsiniz.
read( $fh, $var, -s $fh);
Bu üçüncü argüman, $fh dosya tanıtıcısındaki verilerin bayt boyutunu test eder ve şunu okur:
$var arabelleğine birçok bayt.
Ne kadar yapabilmek I okumak in a dosya by paragraflar?
$/ değişkenini kullanın (ayrıntılar için perlvar'a bakın). Ortadan kaldırmak için "" olarak ayarlayabilirsiniz.
boş paragraflar ("abc\n\n\n\ndef", örneğin, iki paragraf olarak kabul edilir ve
üç) veya boş paragrafları kabul etmek için "\n\n".
Boş bir satırın içinde boşluk olmaması gerektiğini unutmayın. Böylece "fred\n \nstuff\n\n" birdir
paragraf, ancak "fred\n\nstuff\n\n" ikidir.
Ne kadar yapabilmek I okumak a tek karakter itibaren a dosya? Konum the tuş takımı?
Çoğu kütükbelirteç için yerleşik "getc()" işlevini kullanabilirsiniz, ancak (kolayca) çalışmayacaktır.
bir terminal cihazında. STDIN için, ya CPAN'dan Term::ReadKey modülünü kullanın ya da
perlfunc'ta "getc" içindeki örnek kod.
Sisteminiz taşınabilir işletim sistemi programlama arabirimini (POSIX) destekliyorsa,
yankı işlemeyi de kapattığını not edeceğiniz aşağıdaki kodu kullanabilirsiniz.
#!/usr/bin/Perl -w
sıkı kullanın;
$| = 1;
(1..4) için {
"ver:" yazdır;
benim $var = getone();
print "--> $aldı\n";
}
çıkış;
BAŞLA {
POSIX qw(:termios_h) kullanın;
my ($terim, $oterm, $echo, $noecho, $fd_stdin);
benim $fd_stdin = fileno(STDIN);
$term = POSIX::Termios->new();
$term->getattr($fd_stdin);
$oterm = $term->getlflag();
$yankı = EKO | ECHOK | ICANON;
$noecho = $oterm & ~$echo;
alt cbreak {
$term->setlflag($noecho);
$term->setcc(VTIME, 1);
$term->setattr($fd_stdin, TCSANOW);
}
alt pişmiş {
$term->setlflag($oterm);
$term->setcc(VTIME, 0);
$term->setattr($fd_stdin, TCSANOW);
}
alt getone {
$anahtarım = '';
cbreak();
sysread(STDIN, $anahtar, 1);
pişmiş();
$ anahtarını döndür;
}
}
SON { pişmiş() }
CPAN'ın Term::ReadKey modülünün kullanımı daha kolay olabilir. Son sürümler ayrıca şunları içerir:
taşınabilir olmayan sistemler için de destek.
Terim::ReadKey'i kullanın;
$tty'mi aç, '<', '/dev/tty';
print "Bana bir karakter ver: ";
ReadMode "ham";
benim $key = ReadKey 0, $tty;
Okuma Modu "normal";
printf "\n%s dediniz, karakter numarası %03d\n",
$anahtar, ord $anahtar;
Ne kadar yapabilmek I söylemek olup olmadığını var a karakter bekleme on a kütük sapı?
Yapmanız gereken ilk şey, Term::ReadKey uzantısını
CPAN. Daha önce de belirttiğimiz gibi, artık taşınabilir olmayanlar için sınırlı desteğe sahiptir (okuyun: değil
açık sistemler, kapalı, tescilli, POSIX değil, Unix değil vb.) sistemler.
Ayrıca bazı şeyler için comp.unix.* adresindeki Sıkça Sorulan Sorular listesine de göz atmalısınız.
şöyle: cevap aslında aynı. Sisteme çok bağlıdır. Işte bir tane
BSD sistemlerinde çalışan çözüm:
alt key_ready {
benim($rin, $nfd);
vec($rin, dosyano(STDIN), 1) = 1;
dönüş $nfd = select($rin,undef,undef,0);
}
Kaç karakterin beklediğini öğrenmek istiyorsanız, FIONREAD ioctl de var.
bakmak için arayın. NS h2ph Perl ile birlikte gelen araç, C içerme dosyalarını dönüştürmeye çalışır.
"gerektirebilir" olan Perl koduna d. FIONREAD sonunda bir fonksiyon olarak tanımlanır.
sys/ioctl.ph Dosya:
'sys/ioctl.ph' gerektirir;
$boyut = paket("L", 0);
ioctl(FH, FIONREAD(), $size) or die "ioctl çağrılamadı: $!\n";
$beden = paketi aç("L", $beden);
If h2ph kurulmamış veya sizin için çalışmıyorsa, grep dahil etme dosyaları elle:
% grep SON OKUMA /usr/dahil/* / *
/usr/include/asm/ioctls.h:#define FIONREAD 0x541B
Veya şampiyonların editörünü kullanarak küçük bir C programı yazın:
% kedi > fionread.c
#Dahil etmek
ana() {
printf("%#08x\n", FIONREAD);
}
^D
% cc -o fionread fionread.c
% ./okundu
0x4004667f
Ardından, taşıma işlemini halefinize bir alıştırma olarak bırakarak sabit kodlayın.
$FIONREAD = 0x4004667f; # XXX: opsys bağımlı
$boyut = paket("L", 0);
ioctl(FH, $FIONREAD, $size) or die "ioctl çağrılamadı: $!\n";
$beden = paketi aç("L", $beden);
FIONREAD, bir akışa bağlı bir kütük tanıtıcı gerektirir, yani yuvalar, borular ve tty
cihazlar çalışıyor, ancak değil dosyaları.
Ne kadar do I do a "kuyruk -F" in perl mi?
İlk deneme
ara($gw_fh, 0, 1);
"seek($gw_fh, 0, 1)" ifadesi mevcut konumu değiştirmez, ancak netleştirir
tanıtıcıdaki dosya sonu koşulu, böylece sonraki "<$gw_fh>", Perl'in yeniden denemesini sağlar
bir şey okumak için.
Bu işe yaramazsa (stdio uygulamanızın özelliklerine bağlıdır), o zaman ihtiyacınız
bunun gibi bir şey daha:
için (;;) {
for ($curpos = tell($gw_fh); <$gw_fh>; $curpos =tell($gw_fh)) {
# bazı şeyleri arayın ve dosyalara koyun
}
# bir süre uyu
search($gw_fh, $curpos, 0); # bulunduğumuz yeri ara
}
Bu hala işe yaramazsa, sıfırlayan IO::Handle'daki "clearer" yöntemine bakın.
tanıtıcıdaki hata ve dosya sonu durumları.
CPAN'dan bir File::Tail modülü de vardır.
Ne kadar do I kopya() a eğe sapı in Perl?
Perlfunc'ta "aç" seçeneğini işaretlerseniz, arama yapmanın birkaç yolunu görürsünüz. açık() meli
iş görmek. Örneğin:
$log'umu aç, '>>', '/foo/logfile';
STDERR, '>&', $log'u açın;
Veya gerçek bir sayısal tanımlayıcıyla bile:
benim $fd = $ENV{MHCONTEXTFD};
$mhcontext'i açın, "<&=$fd"; # sevmek açık(3'lı)
"<&STDIN" öğesinin bir kopya oluşturduğunu, ancak "<&=STDIN" öğesinin bir takma ad oluşturduğunu unutmayın. Bu, kapatırsanız anlamına gelir
takma adlı bir tanıtıcı, tüm takma adlar erişilemez hale gelir. Bu, kopyalanan biriyle doğru değildir.
Hata denetimi her zaman olduğu gibi okuyucuya bir alıştırma olarak bırakılmıştır.
Ne kadar do I kapat a dosya açıklayıcısı by sayı?
Herhangi bir nedenle, kütük tanıtıcısı yerine bir dosya tanıtıcınız varsa (belki
"POSIX::open"), POSIX modülünden "close()" işlevini kullanabilirsiniz:
POSIX'i kullanın ();
POSIX::kapat( $fd);
Perl "close()" işlevi bazı şeyler için kullanılacağından, bu nadiren gerekli olmalıdır.
"MHCONTEXT" ile olduğu gibi sayısal bir tanımlayıcının bir kopyası olsa bile Perl'in kendini açtığını
üstünde. Ancak gerçekten zorundaysanız, bunu yapabilirsiniz:
'sys/syscall.ph' gerektirir;
benim $rc = sistem çağrısı(SYS_close(), $fd + 0); # sayısalı zorlamalı
die "$fd: $ sistemi kapatılamıyor!" $rc == -1;
Veya, sadece açık(3S) "open()" özelliği:
{
$fh'imi aç, "<&=$fd" veya öl "fd=$fd yeniden açılamıyor: $!";
yakın $fh;
}
Neden Şimdi olamaz I kullanım "C:\temp\foo" in DOS yollar? Neden Şimdi etmez "C:\temp\foo.exe" çalışır?
Eyvah! Bu dosya adına bir sekme ve bir form beslemesi koymanız yeterli! Unutmayın ki içinde
çift tırnaklı dizeler ("böyle\böyle"), ters eğik çizgi bir kaçış karakteridir. tam liste
Bunlardan biri perlop'ta "Alıntı ve Alıntı Benzeri Operatörler" içindedir. Şaşırtıcı olmayan bir şekilde, sahip değilsin
eski DOS'unuzda "c:(tab)emp(formfeed)oo" veya "c:(tab)emp(formfeed)oo.exe" adlı bir dosya
dosya sistemi.
Dizelerinizi tek bir alıntı yapın veya (tercihen) eğik çizgi kullanın. Tüm DOS ve
MS-DOS 2.0 gibi bir şeyden bu yana Windows sürümleri "/" ve "\" öğelerini aynı şekilde ele almıştır.
bir yolda, Perl veya POSIX kabuğu ile çakışmayan yolu da kullanabilirsiniz,
ANSI C ve C++, awk, Tcl, Java veya Python, sadece birkaçından bahsetmek gerekirse. POSIX yolları daha fazladır
taşınabilir de.
Neden Şimdi etmez küre("*.*") almak herşey the dosyalar?
Unix olmayan bağlantı noktalarında bile, Perl'in glob işlevi standart Unix globbingini takip ettiğinden
anlambilim. Tüm (gizli olmayan) dosyaları almak için "glob("*")" gerekir. Bu yapar küre ()
eski sistemlere bile taşınabilir. Bağlantı noktanız, tescilli küreselleştirme işlevlerini şu şekilde içerebilir:
kuyu. Ayrıntılar için belgelerine bakın.
Neden Şimdi yok Perl izin me silmek salt okunur dosyalar? Neden Şimdi yok "-BEN" yenmek korumalı dosyalar? değil Re-Tweet
a böcek in Perl?
Bu, ayrıntılı ve özenli bir şekilde aşağıdaki bölümlerde açıklanmıştır: dosya-dir-izinleri "Uzaktaki makale
Bilmek İstediğinden Daha Fazlası" koleksiyonu
<http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz>.
Yönetici özeti: dosya sisteminizin nasıl çalıştığını öğrenin. Bir dosyadaki izinler ne diyor
o dosyadaki verilere olabilir. Bir dizindeki izinler neler olabileceğini söylüyor
bu dizindeki dosyaların listesine. Bir dosyayı silerseniz, adını da kaldırmış olursunuz.
dizinden (bu nedenle işlem, dizinin izinlerine değil, dizinin izinlerine bağlıdır)
dosya). Dosyaya yazmaya çalışırsanız, dosyanın izinleri,
izinlisin.
Ne kadar do I seçmek a rasgele hat itibaren a dosya?
Dosyayı bir veritabanına yüklemek veya dosyadaki satırları önceden indekslemek dışında,
yapabileceğin birkaç şey.
İşte Camel Kitabından bir rezervuar örnekleme algoritması:
şerit;
rand($.) < 1 && ($satır = $_) while <>;
Bunun, dosyanın tamamını okumaya göre uzayda önemli bir avantajı vardır.
bu yöntemin kanıtı The Sanat of Bilgisayar Programlama , Cilt 2, Bölüm 3.4.2, tarafından
Donald E. Knuth.
Bu algoritma için bir işlev sağlayan File::Random modülünü kullanabilirsiniz:
File::Random qw/random_line/;
benim $line = random_line($dosyaadı);
Diğer bir yol, tüm dosyayı bir dizi olarak ele alan Tie::File modülünü kullanmaktır.
Basitçe rastgele bir dizi öğesine erişin.
Neden Şimdi do I almak tuhaf alanlarda ne zaman I baskı an dizi of çizgiler?
(brian d foy'un katkılarıyla)
Diziyi yazdırırken dizinizin öğeleri arasında boşluklar görüyorsanız,
muhtemelen diziyi çift tırnak içine alıyorlar:
@animals = qw(deve lama alpaka vicuna);
print "hayvanlar: @hayvanlar\n";
Bunu yapan "baskı" değil, çift tırnaktır. Bir diziyi her enterpolasyon yaptığınızda
bir çift alıntı bağlamında, Perl öğeleri boşluklarla (veya $" içindeki her neyse, ki bu
varsayılan olarak bir boşluktur):
hayvanlar: deve lama alpaka vicuna
Bu, enterpolasyon olmadan diziyi yazdırmaktan farklıdır:
@animals = qw(deve lama alpaka vicuna);
print "hayvanlar: ", @hayvanlar, "\n";
Şimdi çıktının elemanları arasında boşluklar yok çünkü elemanları
@animals "yazdırılacak" listenin bir parçası haline gelir:
hayvanlar: camelllamaalpacavicuna
@array öğelerinin her biri yeni satırla bittiğinde bunu fark edebilirsiniz. bekliyorsun
satır başına bir öğe yazdırmak için, ancak ilk satırdan sonraki her satırın girintili olduğuna dikkat edin:
bu bir çizgi
bu başka bir çizgi
bu üçüncü satır
Bu fazladan boşluk, dizinin enterpolasyonundan gelir. koymak istemiyorsan
dizi öğeleriniz arasında herhangi bir şey varsa, diziyi çift tırnak içinde kullanmayın. Gönderebilirsin
onlarsız yazdırmak için:
@lines yazdır;
Ne kadar do I çapraz a rehber ağaç?
(brian d foy'un katkılarıyla)
Perl ile birlikte gelen File::Find modülü, bir
dizin yapısı. Perl ile birlikte gelir. Basitçe "bul" alt programını bir a ile çağırın.
geri arama alt yordamı ve geçiş yapmak istediğiniz dizinler:
Dosya::Bul'u kullanın;
bul( \&istenen, @dizinler);
alt aranan {
# $File::Find::name içindeki tam yol
# $_ içinde sadece dosya adı
... Ne yapmak istiyorsan onu yap ...
}
CPAN'dan indirebileceğiniz File::Find::Closures, kullanıma hazır birçok
File::Find ile kullanabileceğiniz alt programlar.
CPAN'dan indirebileceğiniz Dosya::Finder, geri aramayı oluşturmanıza yardımcı olabilir.
"find" komut satırı yardımcı programının sözdizimine daha yakın bir şey kullanan alt yordam:
Dosya::Bul'u kullanın;
Dosya::Finder'ı kullanın;
my $deep_dirs = Dosya::Finder->depth->type('d')->ls->exec('rmdir','{}');
find( $deep_dirs->as_options, @places);
CPAN'dan indirebileceğiniz File::Find::Rule modülü de benzer bir arayüze sahiptir,
ancak geçiş sizin için de geçerli:
Dosya::Bul::Kural kullanın;
@files = Dosya::Bul::Kural->dosya()
->ad( '*.pm' )
->in( @INC );
Ne kadar do I silmek a rehber ağaç?
(brian d foy'un katkılarıyla)
Boş bir dizininiz varsa, Perl'in yerleşik "rmdir"ini kullanabilirsiniz. dizin ise
boş değil (yani, dosya veya alt dizin yok), ya kendiniz boşaltmanız gerekiyor (birçok
iş) veya size yardımcı olacak bir modül kullanın.
Perl ile birlikte gelen File::Path modülü, ilgilenebilecek bir "remove_tree"ye sahiptir.
tüm zor işler senin için:
Dosya::Yol qw(remove_tree);
remove_tree( @dizinler);
File::Path modülü ayrıca daha eski "rmtree" alt rutini için eski bir arayüze sahiptir.
Ne kadar do I kopya an tüm dizin?
(Shlomi Fish'in katkılarıyla)
"cp -R" eşdeğerini yapmak (yani tüm dizin ağacını özyinelemeli olarak kopyalamak)
taşınabilir Perl, ya kendiniz bir şeyler yazmanız ya da iyi bir CPAN modülü bulmanız gerekecek
File::Copy::Recursive gibi.
YAZAR VE TELİF HAKKI
Telif hakkı (c) 1997-2010 Tom Christiansen, Nathan Torkington ve belirtildiği gibi diğer yazarlar.
Tüm hakları saklıdır.
Bu dokümantasyon ücretsizdir; yeniden dağıtabilir ve/veya aynı şartlar altında değiştirebilirsiniz
Perl'in kendisi olarak.
Dağıtımından bağımsız olarak, buradaki tüm kod örnekleri kamuya açıktır. Sen
Bu kodu ve onun türevlerini kendi programlarınızda kullanmanıza izin verilir ve teşvik edilir
uygun gördüğünüz gibi eğlence için veya kâr için. Kredi veren kodda basit bir yorum
SSS nazik olurdu, ancak gerekli değildir.
onworks.net hizmetlerini kullanarak perlfaq5'yi çevrimiçi kullanın