Mam linijkę tekstu typu:

value,value,,,value,value

Chcę, aby dwie puste wartości zostały zastąpione inną wartością. Coś jak:

value,value,hello,hello,value,value

Obecnie próbuję czegoś takiego:

sed -e 's/^,/hello,/' -e 's/,$/,hello/' -e 's/,,/,hello,/g'

To wychwytuje puste wartości na początku, końcu i środku. ALE, nie przechwytuje dwóch kolejnych pustych wartości z rzędu. Jak mogę zaktualizować wzorce wyrażeń regularnych, aby w środku pojawiła się nieskończona liczba kolejnych pustych wartości?

4
Steve Prentice 22 czerwiec 2011, 00:28
Sed nie wspiera patrzenia w przód ani w tył, prawda. To sprawia, że ​​jest to trudniejsze. Czy w Twojej sytuacji są jakieś inne smaki regex?
 – 
agent-j
22 czerwiec 2011, 00:36
man sed mówi, że mogę użyć --regexp-extended: użyj rozszerzonych wyrażeń regularnych w skrypcie.
 – 
Steve Prentice
22 czerwiec 2011, 00:44
Rozwiązanie nie musi również używać sed. Zrobi to każde powszechnie dostępne narzędzie (tj. instalowane domyślnie w większości dystrybucji).
 – 
Steve Prentice
22 czerwiec 2011, 00:49

3 odpowiedzi

Najlepsza odpowiedź

A co z tym jednowierszowym perlem:

echo ',value,,,value,' | perl -pe 's/^(?=,)|(?<=,)(?=,|$)/hello/g'
# hello,value,hello,hello,value,hello
5
mhyfritz 22 czerwiec 2011, 02:01
Zbliżam się, ale w jednym scenariuszu mi się nie udaje. Linia ma cztery pola i wszystkie są puste: ,,,. Twój perl produkuje hello,,hello,hello
 – 
Steve Prentice
22 czerwiec 2011, 01:02
Prentice: Myślę, że zauważyłem błąd i zaktualizowałem jednolinijkę. Daj mi znać jak idzie.
 – 
mhyfritz
22 czerwiec 2011, 01:04
Cieszę się, że mogłem pomóc. Btw, okazuje się, że wcale nie potrzebujesz chwytów. Sprawdź zaktualizowaną wersję.
 – 
mhyfritz
22 czerwiec 2011, 01:26
Jestem trochę zdezorientowany, po co jest pierwsze odwołanie wsteczne? Ok, edytowałeś to... nie ma więcej odniesień :-) to jest magia
 – 
Milde
22 czerwiec 2011, 01:49
Hehe, przeładowanie strony czasami pomaga ;) Btw wszystkim, właśnie zrobiłem kolejną drobną zmianę, aby była bardziej zwarta. Ostatnia edycja tego! (ufnie ;)
 – 
mhyfritz
22 czerwiec 2011, 02:00

Nie sądzę, że możesz to zrobić za pomocą pojedynczego polecenia zamiany, ponieważ Sed zastępuje tylko nienakładające się wystąpienia twojego wzorca. Ten brzydki hack może zadziałać, ale wymaga, abyś zablokował jeszcze jeden znak (wybrałem ';') w twoich wartościach:

$ echo 'value,value,,,value,value' | sed -r 's/,/,;/g;s/(^|;)(,|$)/\1hello\2/g;s/,;/,/g'
value,value,hello,hello,value,value
2
r3c 22 czerwiec 2011, 00:39
+1 Spryt. Tak więc, zamieniasz co , na ,;, wykonujesz trochę magii, a następnie przywracasz ograniczniki. To działa, ale zamierzam poczekać z przyjęciem odpowiedzi, ponieważ mam nadzieję, że jest na to mniej brzydki sposób.
 – 
Steve Prentice
22 czerwiec 2011, 01:04
No cóż, możesz też dokonać zamiany dwa razy, w ten sposób: echo 'value,value,,,value,value' | sed -r 's/(^|,)(,|$)/\1hello\2/g;s/(^|,)(,|$)/\1hello\2/g' Ale to też jest brzydkie :)
 – 
r3c
22 czerwiec 2011, 01:08
+1 za zrobienie tego z sed, gdy po Twojej odpowiedzi pojawiła się część „to nie musi być sed”. A niektórzy seds będą chcieli -E zamiast -r do tego.
 – 
mu is too short
22 czerwiec 2011, 01:11
Właściwie lubię takie podejście. :) Każdy łapie drugiego.
 – 
Steve Prentice
22 czerwiec 2011, 01:13

Inne jednolinijki perlowe:

perl -we '$_=<>; while(s/,,/,hello,/) {}; print;'  value.txt

perl -we 'print join ",", map { $_ || 'hello' } split /,/, <>;' value.txt
1
TLP 22 czerwiec 2011, 02:19