2010-12-14 16 views
6

Jak wykonać sed w określonych częściach linii? I, przeciwnie, jak sprawić, aby sed nie działał na określonych częściach linii?Sposób działania tylko na części linii

Przykłady:

"A a A a (A a) A (a A) a" 

Jak, na przykład, wymienić wszystkie A S z T s tylko pomiędzy ( i ) uzyskanie:

"A a A a (T a) A (a T) a" 

A biorąc pod Następny przykład input:

"F f F f (F f) F (f F) f" 

Jak na przykład wymienić wszystkie F sz X s, ale nie pomiędzy ( i ) do otrzymujemy:

„X f X f (K), X (K) f "

Przeszukałem Google, ale nie znalazłem niczego użytecznego. Sądzę, że to ogólne pytanie o sed. Problem jest sprowadzalny do ogólnych "szablonów" sed, mam nadzieję.

  1. mający OD i DO następnie działać tylko między nimi (na wszystkich wystąpień na danej linii)
  2. mających od a do działania w innym miejscu niż między nimi ...
  3. szczególny przypadek kiedy OD i DO są takie same (od „i” lub „foo” i „foo” itd.) zarówno 1. i 2.

powinien pracować z każdej operacji, a nie tylko podstawienia, ale także drukowanie itd., takie jak drukowanie wszystkiego między ciągami "FOO" i "BAR" w łańcuchu.

"1 2 3 BAR a b c FOO d e f BAR g a h FOO i j k BAR l m n FOO o p q" 

Rezultatem będzie

" d e f i j k " 

Więc, ogólne przykłady, w jaki sposób to zrobić byłoby bardzo mile widziane. Wydaje się również, że to pytanie jest dość powszechne, ale nie ma jeszcze dobrego poradnika na temat Google. Zgaduję również, że odpowiedź na to pytanie byłaby dość trudna. Proszę również nie dawać wskazówek jak to zrobić używając Perla, AWK czy cokolwiek innego niż sed. To pytanie jest naprawdę tylko sed-pytanie.

+0

Starałem się jak mogłem. Mój pomysł polegał na podzieleniu linii na części przez FROM i TO (w jakiś sposób), a następnie "jakoś" (nie wiem jak jeszcze), aby działał albo na parzystych lub nieparzystych częściach albo na podobnej zasadzie. Gdybym wiedział, jak to zrobić, nie prosiłbym o to tutaj. I jest bardzo prawdopodobne, że mój pomysł podziału może być błędny. Jest to dość trudne i wcześniej używał sed tylko do prostych zadań. – mjf

Odpowiedz

1

Dziel i rządź.

Wstawianie linii pomocniczych w celu oddzielenia segmentów, a następnie użycie linii początkowych, początku linii (^), zakończenia wiersza ($) i znaków ogranicznika (w tym przypadku nawiasów) jako kotwic i pętli. Dodane nowe linie są usuwane na końcu.

$ echo "A a A a (A a) A (a A) a" | 
    sed 's/([^)]*)/\n&/g; 
     :a; 
      s/\(\n([^)]*\)A\([^)]*)\)/\1T\2/; 
     ta; 
     s/\n//g' 
A a A a (T a) A (a T) a 
$ echo "F f F f (F f) F (f F) f" | 
    sed 's/(/\n(/g; 
     s/)/)\n/g; 
     :a; 
      s/\([^(]*\)F\([^)]*\(\n\|$\)\)/\1X\2/g; 
     ta; 
     s/\n//g' 
X f X f (F f) X (f F) f 
$ echo "1 2 3 BAR a b c FOO d e f BAR g a h FOO i j k BAR l m n FOO o p q" | 
    sed 's/^/BAR/; 
     s/$/FOO/; 
     s/FOO/&\n/g; 
     s/BAR/\n&/g; 
     s/BAR[^\n]*\n//g; 
     s/[^\n]*FOO\n//g; 
     s/\n//g' 
d e f i j k 
+0

Dziękuję. Daj mi trochę czasu, aby przejść przez to, proszę. – mjf

+0

Co, jeśli chciałbym zamienić, powiedzmy, wszystko wokół sekcji otoczonych znakami "[" i "]", jak to jest w wyrażeniu regularnym? Zadanie jest podobne do przekształcania zwykłego wyrażenia regularnego (gdzie wszystkie znaki "() [] |} | +?" Nie wymagają ewakuacji), na przykład, wyrażenie grep lub sed, gdzie specjalne znaki muszą być usunięte. Mam na myśli, biorąc pod uwagę, powiedzmy, następne wyrażenie sed bez ucieczki od postaci, które muszą zostać usunięte ze składni sed, ponieważ nadają im specjalne znaki, które chciałbym zastosować w programie AROUND space next sed: "s/\\ ([] [() {} | +?] \\)/\\\ 1/g ". Dane wejściowe będą takie same "s/([] [() {} | +?])/\\\ 1/g". – mjf

+0

Utrzymuję bazę danych wyrażenia regularnego POSIX w formularzu, w którym "^. [$() | * +? {\" Znaki muszą być zmienione z "\", aby były "nietypowe" (man 7 regex). Potrzebuję skryptu do przekształcenia tych wyrażeń regularnych w formę, której potrzebuję w danym momencie, na przykład grep (1). Następnie potrzebuję go jako, powiedzmy, sed (1) formularza, lub edytora vi formy itp. Ręczne przekształcanie wyrażeń jest bolesne, a teraz db wzrósł do całkiem ogromnego rozmiaru. Aby ręcznie przekształcać wszystkie wyrażenia, nawet w tak sprytnym edytorze jak vi, jest to bolesne. Potrzebuję skryptu do tego zadania, co było moją pierwotną motywacją do zadawania tego pytania. – mjf

1

To może pracować dla Ciebie (GNU sed):

sed ':a;s/\(([^)]*\)A/\1T/;ta' file # for case 1 

sed ':a;s/\(([^)]*\)F/\1\n/;ta;y/F\n/TF/' file # for case 2 

Na razie 1 użyć pętli zastąpienia A 's wewnątrz wsporników do T wieku.

w przypadku 2 wykorzystać takie same jak powyżej, aby zmienić F jest nawiasach do nowej linii, to tłumaczyć F 'S nowe linie do X 'S' S F odpowiednio.

Przypadek 3 jest nieco bardziej zaangażowane, ale można zrobić w 2 poleceń zastępczych:

sed -r 's/FOO|BAR/\n&/g;s/[^\n]*(\nBAR[^\n]*)*(\nFOO([^\n]*)\nBAR)?(\nFOO[^\n]*$)?/\3/g' file 

pierwszy prefiks każdy FOO i BAR struny z nowej linii. Następnie poszukaj wszystkich kombinacji FOO i BAR i zachowaj tylko ciągi znaków między FOO i BAR. Nowe znaki zezwalają na użycie klasy ujemnej w celu uproszczenia procedury.

Powiązane problemy