2013-07-02 7 views
5

Pracuję transfer plików między serwerami, które są rejestrowane. Te muszą być ostatecznie przesłane do bazy danych, więc przygotowuję je do sprawdzania błędów. Każdy wpis w pliku dziennika reprezentował przelew i ma format:Dzielenie łańcucha zawierającego rozdzielone spacjami "klucz = wartość" parami, gdy wartość może również zawierać spację

key1=value1 key2=value2 

dla 16 pól. Większość transferów jest w porządku, z wyjątkiem sytuacji, gdy ktoś przenosi plik, którego nazwa zawiera spację. To zakłóca przetwarzanie, ponieważ po prostu nazywam split w przestrzeni w moim skrypcie perla. Przykład:

DATE=20130411140806.384553 HOST=somehost PROG=someserver NL.EVNT=FTP_INFO START=20130411140806.384109 USER=someuser FILE=/extended_path/Wallpapers Folder.ico BUFFER=98720 BLOCK=262144 NBYTES=0 VOLUME=/ STREAMS=2 STRIPES=1 DEST=[0.0.0.0] TYPE=STOR CODE=226 

To tylko jeden przykład, w którym występuje spacja między "Wallpapers" i "Folder.ico". Czy istnieje sposób na zaprojektowanie wyrażenia regularnego, które może uwzględnić to i podzielić wszystkie pary klucz-wartość? Jeśli nie ma sposobu, aby to zrobić, możesz zaproponować inny sposób, aby to zrobić?

Moim celem jest zastąpienie tych spacji nic (tj. Usunąć spację) lub podkreślenie, aby po uruchomieniu skryptu do załadowania do bazy danych nie wystąpił problem z dzieleniem pojedynczej przestrzeni. Używam perla, aby zrobić to wszystko przy okazji.

+0

Czy zawsze możesz liczyć na to, że pola są w tej kolejności? –

+0

Proponuję dodać wartości jako ciągi zacytowane, wszystkie wartości lub przynajmniej te zawierające białe znaki. – 0xCAFEBABE

+0

@DanielGimenez Tak. Jest rejestrowany przez serwer. – shaun

Odpowiedz

9

Można wyszukiwać niepożądanych przestrzeni za pomocą lookahead, który zapewnia, że ​​nie poprz klucza:

$input =~ s/[ ](?!\S+=)/_/g; 

uprzedzona zapewnia, że ​​nie ma = przed następnym znakiem spacji.

Następnie można dzielić na spacjach.

Alternatywnie, aby dopasować się od razu, można zastosować podobną technikę:

while ($input =~ m/(\S+)=((?:\S|[ ](?!\S+=))+)/g) 
{ 
    # $1 is the key 
    # $2 is the value 
} 

Dla wartości powtarzamy ani znaków spoza przestrzeni lub pomieszczenia, które nie poprz klucz.

Working demo.

Jeśli klucze są zawsze wielkimi literami, można wymienić cały \S+ w moim kodu z [A-Z]+.

+0

+1 w wyrażeniu regularnym. Nie mogłem być tak zwięzły jak rozwiązanie. Dobre wykorzystanie zanegowanych białych znaków. –

+0

Dziękuję bardzo, Sir! To działało naprawdę dobrze. – shaun

Powiązane problemy