Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]operacje na plikach
Forum PHP.pl > Forum > Przedszkole
lamcpp
mam plik *.txt, który wygląda mniej więcej tak:
2.0 1992.11 1975.10 22
1.1 1992.11 1975.10 35
1.1 SLE 1972.11 1975.10 40
&1300 MARATHON 1973.109 1975.08 42
...

Pytania:
-jak /przy pomocy jakiej funkcji dodać na początku każdego wiersza znak "$" (ale dodać tylko w tych wierszach, które nie mają znaku "&" na początku)
-jak usunąć wszystkie nadmiarowe spacje powyżej jednej
- za pomocą jakiej funkcji dodać przed ostatnimi numerami w rzędzie czyli przed 22, 35, 40, 42 znak ":", jak pomiędzy datami dodać znak "-"?
patryk9200
poczytaj o wyrażeniach regularnych, wystarczy, że skopiujesz zawartość pliku do zmiennej, "przelecisz" całą kilkoma wyrażeniami regularnymi a potem wynik zapisać.
bastard13

Wyrażenia regularne są rozwiązaniem twoich problemów:)
http://php.net/manual/en/book.pcre.php
Otwórz sobie plik z prawami do odczytu i zapisu. Przeleć pętlą po każdej linii, a tam wykonuj odpowiednie operacje:

Ad 1)
Sprawdź funkcją preg_match(), czy na początku linii jest znak &, jeżeli nie to dodaj $.
http://www.php.net/manual/en/function.preg-match.php

Ad 2)
http://www.php.net/manual/en/function.preg-replace.php

Ad 3)
Tutaj też preg_replace() z tym, że zabawa będzie ciekawsza:) Oprócz tego możesz zrobić exploda na linii po spacji i też zrobisz to, co chesz.
mortus
@bastard13 Ale po co tak kombinować?
Wszystko można funkcjąi preg_replace() załatwić i to wywołując ją jeden raz:
  1. $sourceFileName = 'data.txt'; // tutaj zamiast data.txt wpisujesz nazwę swojego pliku
  2. $destinationFileName = 'data_'.time().'.txt'; // tutaj natomiast wpisujesz nazwę nowego pliku
  3. $content = file_get_contents($sourceFileName);
  4.  
  5. $patterns[0] = '#^[^&].*$#m';
  6. $patterns[1] = '#\s{2,}#';
  7. $patterns[2] = '#\s([0-9]+$)#m';
  8. $patterns[3] = '#([0-9]{4}.[0-9]{2})\s([0-9]{4}.[0-9]{2})#';
  9. $replacements[0] = '$$0';
  10. $replacements[1] = ' ';
  11. $replacements[2] = ':$1';
  12. $replacements[3] = '$1-$2';
  13.  
  14. $newContent = preg_replace($patterns, $replacements, $content);
  15. file_put_contents($destinationFileName, $newContent);

Dla przypadku 3 zamieniam spacje odpowiednio na : i -. Jeśli potrzebujesz tam również spacji, to dopisz je do $replacements[2] i $repecements[3].
bastard13
@mortus
Ano rzeczywiście:)
Tylko to \s (dowolny biały znak) zamieniłby na \040 (spacja)
lamcpp
A jak usunąć wszystkie puste linie z pliku?
Tzn. mam plik
pierwszy wpis

drugi wspi
trzeci wpis

czwarty wpis

I chciałbym te puste linie pomiędzy wpisami zlikwidować
erix
Alergia na wyszukiwarkę?

http://forum.php.pl/index.php?showtopic=45678
mortus
Można to również zrobić szybciej:
  1. $sourceFileName = 'data.txt';
  2. $content = file_get_contents($sourceFileName);
  3. $pattern = '#^[^\r\n].*$#m';
  4. preg_match_all($pattern, $content, $matches);
  5. $contentWithoutEmptyLines = implode($matches[0]);

erix
Ciekawe...

Ciekawe, czy posiadając plik o rozmiarze kilkuset MiB użyjesz tego samego.
lamcpp
mając taki warunek:
$wzorzec[0]='#([0-9]{4}.[0-9]{2})\s([0-9]{4}.[0-9]{2})\s#';
$zamiana[0]='$1-$2:';

chciałbym dodać do niego by wzorzec nie odnosił się do elementów które rozpoczynają się od znaku $ i & (ale odnosił się do wszystkich pozostałych)
Jak to zrobić? Próbowałem tak zmieniając wzorzec:
$wzorzec[0]='[^&]*#([0-9]{4}.[0-9]{2})\s([0-9]{4}.[0-9]{2})\s#';
$zamiana[0]='$1-$2:';
ale to nie daje efektu.
Również problem mam z przedstawionym na forum:
$patterns[1] = '#\s{2,}#';
$replacements[1] = ' ';
który usuwa spacje. Tylko usuwa..zbyt dokładnie, tzn nie wiem dlaczego ale poza spacjami usuwa tez znak nowej linii, przez co wszystkie linie się "pozlepiały" ze sobą.
ps. dziękuję za dotychczasowe odpowiedzi
mortus
Cytat(erix @ 8.06.2011, 10:41:41 ) *
Ciekawe...

Ciekawe, czy posiadając plik o rozmiarze kilkuset MiB użyjesz tego samego.

Podejrzewam, że przy pliku o rozmiarze kilkudziesięciu MiB byłyby już problemy, a przetwarzanie plików o rozmiarze kilkuset MiB dla obu metod byłoby czasochłonne, choć z pewnością funkcja file() wygrałaby ewentualną rywalizację.
Osobiście przerzuciłbym dane do bazy danych.

Wracając do tematu:
  1. $wzorzec[0]='#^[^&|$].*([0-9]{4}.[0-9]{2})\040([0-9]{4}.[0-9]{2}).*$#m';
  2. $zamiana[0]='$1-$2:';

We wszystkich wzorcach zamień \s na \040, jak radził bastard13, a nie będzie problemów ze "zjedzonym" znakiem nowej linii.

Swoją drogą mój poprzedni kod nie działa do końca prawidłowo (jeszcze nie wiem dlaczego). Natomiast do usunięcia pustych linii możemy również wykorzystać funkcję preg_replace():
  1. $sourceFileName = 'data.txt';
  2. $content = file_get_contents($sourceFileName);
  3. $pattern = "#(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+#";
  4. $replacement = "\n";
  5. $contentWithoutEmptyLines = preg_replace($pattern, $replecement, $content);
lamcpp
Chciałbym aby wyrażenie, które nie ma jako pierwszego znaku & otrzymało na początku linii znak ^ (a następne znaki żeby pozostały takie same
Czyli mam tekst:
&ACTdf hatchbed 1995.09 2000.09
1,6 1995.09 2000.09 66
2,6 1993.09 2001.09 62
I chciałbym by wyglądał on tak
&ACTdf hatchbed 1995.09 2000.09
^1,6 1995.09 2000.09 66
^2,6 1993.09 2001.09 62
Próbowałem już wielu sposobów żeby to zrobić np
$wzorzec[1]='#^[^&](.*)$#m';
$zamiana[1]='^$1';
ale to nie działa tak jak trzeba (ucina mi początek wyrazenia)

W pozostałych przykładach też nie działa to tak jak trzeba, zamiast negować cały ciąg, neguje mi pojedynczy znak;/
mortus
Cytat(lamcpp @ 8.06.2011, 21:50:23 ) *
Chciałbym aby wyrażenie, które nie ma jako pierwszego znaku & otrzymało na początku linii znak ^ (a następne znaki żeby pozostały takie same
Czyli mam tekst:
&ACTdf hatchbed 1995.09 2000.09
1,6 1995.09 2000.09 66
2,6 1993.09 2001.09 62
I chciałbym by wyglądał on tak
&ACTdf hatchbed 1995.09 2000.09
^1,6 1995.09 2000.09 66
^2,6 1993.09 2001.09 62
Próbowałem już wielu sposobów żeby to zrobić np
$wzorzec[1]='#^[^&](.*)$#m';
$zamiana[1]='^$1';
ale to nie działa tak jak trzeba (ucina mi początek wyrazenia)

W pozostałych przykładach też nie działa to tak jak trzeba, zamiast negować cały ciąg, neguje mi pojedynczy znak;/

Ale przecież wyżej masz podobne wyrażenie ($patterns[0], $replacements[0]). Czy tak ciężko jest zamienić znak $ na ^ w $replacements[0]?
lamcpp
Teraz juz rozumiem:)
Jeszcze jedno pytanie (juz ostatnie) z ktorym nie mogę sobie poradzic:
otoz mam dwa rodzaje linijek tekstu(z pojedynczą datą w postaci 2000.02, oraz z dwoma datami w postaci 2000.02 2005.03).
Oto przykłady:
1) pojedyncza data:
&TRANS 1996.08
&MON 1976.04
2)podwójna data
&TRANS 1996.08 1999.05
&MON 1976.04 2003.05

Chciałbym aby zostały zmienione tylko te linijki, które zawierają pojedyńczą datę. Wpisuję więc kod:
  1. $wzorzec[4]='#&(.*)([0-9]{4})[,|.]([0-9]{2})#m';
  2. $zamiana[4]='&$1:$2.$3-';

Niestety kod działa również na linijki z podwójną datą, jak więc zapisać by działało tylko z pojedynczą datą?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.