2012-09-24 25 views
7

Jestem początkującym sed. Wiem, że jest to możliwe do zastosowania polecenia (lub zestaw poleceń) w pewnym zakresie linii jak taksed - łączenie szeregu wybranych linii

sed '/[begin]/,/[end]/ [some command]' 

gdzie [begin] jest wyrażeniem regularnym, który wyznacza linię początku zakresu i [end] jest regularna wyrażenie określające końcową linię zakresu (ale jest zawarte w zakresie).

Próbuję użyć tego, aby określić zakres linii w pliku i dołączyć je wszystkie w jednej linii. Oto moja najlepsza próba, która nie działa:

sed '/[begin]/,/[end]/ { 
N 
s/\n// 
} 
' 

jestem w stanie wybrać zestaw wierszy chcę bez problemu, ale po prostu nie może się połączyć je wszystkie w jednej linii. Jeśli ktokolwiek mógłby wskazać mi właściwy kierunek, byłbym bardzo wdzięczny.

Odpowiedz

5

Jednym ze sposobów, za pomocą GNU sed:

sed -n '/begin/,/end/ { H;g; s/^\n//; /end/s/\n/ /gp }' file.txt 
+1

Dziękuję bardzo. Nigdy nie myślałem o korzystaniu z przestrzeni ładowni; Wiele nauczyłem się z twojej odpowiedzi. – Setris

+0

pamiętać, że będzie odrzucać wszystkie inne linie * *. Zobacz poniżej odpowiedź @Thor dla bardziej niezawodnego rozwiązania. – krlmlr

1

Lubię swoje pytanie. Lubię też Sed. Niestety, nie wiem, jak odpowiedzieć na twoje pytanie w Sed; tak jak ty, obserwuję tutaj odpowiedź.

Ponieważ nie Sed odpowiedź jeszcze nie pojawił się tu, oto jak to zrobić w Perlu:

perl -wne 'my $flag = 0; while (<>) { chomp; if (/[begin]/) {$flag = 1;} print if $flag; if (/[end]/) {print "\n" if $flag; $flag = 0;} } print "\n" if $flag;' 
+0

Dziękuję za wdrożenie w Perlu. Miałem zamiar nauczyć się go na chwilę, więc dodam go do mojej kolekcji fragmentów kodu do studiowania. – Setris

2

To proste, jeśli chcesz, aby wybrać niektóre linie i dołącz do nich. Użyj Steve's odpowiedź lub mój alternatywę pipe-to-tr:

sed -n '/begin/,/end/p' | tr -d '\n' 

staje się nieco trudniejsze, jeśli chcesz zachować inne linie, jak również. Oto jak ja to zrobić (z GNU sed):

join.sed

/\[begin\]/ { 
    :a 
    /\[end\]/! { N; ba } 
    s/\n/ /g 
} 

Więc tu jest logika:

  1. Kiedy [begin] linia spotyka się rozpocząć zbieranie linie przestrzeń wzoru z pętlą.
  2. Kiedy [end] znajduje się zatrzymać zbieranie i połączyć przewody.

Przykład:

seq 9 | sed -e '3s/^/[begin]\n/' -e '6s/$/\n[end]/' | sed -f join.sed 

wyjściowa:

1 
2 
[begin] 3 4 5 6 [end] 
7 
8 
9 
+0

dlaczego nie sed -n '/ begin /,/end/p' | gzip | gunzip | tr -d '\ n' w tym czasie? – Valer

+0

@Valer: Nie jestem pewien, czy rozumiem twój punkt widzenia. Jednak dodałem drugi przykład, który może łączyć wybrane linie, zachowując resztę pliku. – Thor

Powiązane problemy