Mam plik w następującym formacie:

abc: A B C D E
abc: 1 2 3 4 5 
def  D E F G H
def: 10 11 12 23 99
...

To jest pierwsza linia z ciągami znaków po ':' jest nagłówkiem następnej linii z liczbami. Chciałbym użyć sed do wyodrębnienia tylko wiersza zaczynającego się od ciągu PATTERN z liczbami w wierszu.

Liczba liczb w wierszu jest zmienna, ale załóżmy, że wiem dokładnie, ile się spodziewam, więc wypróbowałem to polecenie:

% sed 's/^abc: \([0-9]+ [0-9]+ [0-9]+\)$/\1/g' < file.txt

Ale zrzuca wszystkie wpisy z pliku. Co ja robię źle?

0
Mark 2 kwiecień 2020, 18:56

4 odpowiedzi

Najlepsza odpowiedź
  1. sed dokonuje podstawień i wypisuje każdą linię, niezależnie od tego, czy następuje podstawienie, czy nie.

  2. Twoje wyrażenie regularne jest nieprawidłowe. Dopasowałoby tylko trzy liczby oddzielone spacjami, gdyby podano rozszerzoną flagę wyrażenia regularnego (-E). Bez tego nawet tego, ponieważ znak + zostanie zinterpretowany dosłownie.

  3. Najlepiej jest używać adresów i wypisywać tylko te wiersze, które pasują:

sed -nE '/^abc: [0-9]+ [0-9]+ [0-9]+ [0-9]+ [0-9]+$/p' < file.txt

Albo lepiej,

sed -nE '/^abc:( [0-9]+){5}$/p' < file.txt

Flaga -n wyłącza zachowanie "drukuj wszystkie wiersze" funkcji sed opisane w (1). Wydrukowane zostaną tylko wiersze, które dochodzą do polecenia p.

1
Quasímodo 2 kwiecień 2020, 17:21

aby wyodrębnić tylko wiersz zaczynający się od ciągu PATTERN z liczbami w wierszu i Liczba liczb w wierszu jest zmienna oznacza co najmniej jedną liczbę, więc:

$ sed -n '/abc: \([0-9]\+\)/p' file

Wynik:

abc: 1 2 3 4 5 

Przy dokładnie 5 liczbach użyj:

$ sed -n '/abc: \([0-9]\+\( \|$\)\)\{5\}/p' file
1
James Brown 2 kwiecień 2020, 16:02

Z dodatkowym pytaniem @ Marka w komentarzu „Jeśli chcę po prostu wyodrębnić pasujące liczby (i usunąć przedrostek, np. Abc)…” oto wzorzec, który wymyśliłem:

sed -En 's/^abc: (([0-9]+[ \t]?)+)[ \t]*$/\1/gp' file.txt

Używam flagi -E dla rozszerzonych wyrażeń regularnych, aby uniknąć wszystkich potrzebnych znaków specjalnych.
Biorąc pod uwagę ten plik:

abc: A B C D E
abc: 1 2 3 4 5 
abc: 1 c9 A 7f
def  D E F G H
def: 10 11 12 23 99

… To wyrażenie regularne dopasowuje abc: 1 2 3 4 5, jednocześnie wykluczając abc: 1 c9 A 7f - dopuszcza również zmienne białe i końcowe spacje.

1
Stephen P 2 kwiecień 2020, 19:15

Z każdym sedem:

$ sed -n 's/^abc: \([0-9 ]*\)$/\1/p' file
1 2 3 4 5
0
Ed Morton 3 kwiecień 2020, 04:30