Chcę pobrać dwie ostatnie liczby (jedną int, jedną zmiennoprzecinkową; po której następuje opcjonalna spacja) i wypisać tylko je.
Przykład:
foo bar <foo> bla 1 2 3.4
Powinien wydrukować:
2 3.4
Jak dotąd mam:
sed -n 's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/replacement/p'
da mi
foo bar <foo> bla 1 replacement
Jeśli jednak spróbuję zastąpić ją grupą 1, drukowany jest cały wiersz.
sed -n 's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/\1/p'
Jak wydrukować tylko tę sekcję wiersza, która pasuje do wyrażenia regularnego w grupie?
Odpowiedzi:
Dopasuj całą linię, więc dodaj
.*
na początku swojego wyrażenia regularnego. Powoduje to zastąpienie całej linii zawartością grupyecho "foo bar <foo> bla 1 2 3.4" | sed -n 's/.*\([0-9][0-9]*[\ \t][0-9.]*[ \t]*$\)/\1/p' 2 3.4
źródło
-r
opcję lub `--regexp-extended`, w przeciwnym razie otrzymywałem błądinvalid reference \1 on
'polecenia RHS'.(
i)
zamiast\(
i\)
..*
na końcu wyrażenia regularnego, jeśli ciąg, który chcesz wyodrębnić, nie zawsze znajduje się na końcu wiersza..*
jest chciwy, a sed nie ma.*?
(
i)
nie spowoduje to błędu w Ubuntu 16.04. Myślę więc, że ten komentarz jest nieaktualny.grep to właściwe narzędzie do wyodrębniania.
używając swojego przykładu i wyrażenia regularnego:
kent$ echo 'foo bar <foo> bla 1 2 3.4'|grep -o '[0-9][0-9]*[\ \t][0-9.]*[\ \t]*$' 2 3.4
źródło
grep -o
połączeniami potokowymi . stackoverflow.com/a/58314379/117471A jeśli chodzi o jeszcze jedną opcję, wybrałbym awk!
echo "foo bar <foo> bla 1 2 3.4" | awk '{ print $(NF-1), $NF; }'
Spowoduje to podzielenie danych wejściowych (używam tutaj STDIN, ale dane wejściowe mogą z łatwością być plikiem) na spacje, a następnie wydrukuje przedostatnie pole, a następnie ostatnie pole. Te
$NF
zmienne przytrzymaj liczba pól znaleziono po eksplozji na przestrzeniach.Zaletą tego jest to, że nie ma znaczenia, czy zmieni się to, co poprzedza dwa ostatnie pola, o ile tylko chcesz, aby ostatnie dwa pola nadal działały.
źródło
Polecenie cięcia jest przeznaczone właśnie do tej sytuacji. Spowoduje to „wycięcie” dowolnego separatora, a następnie można określić, które fragmenty mają zostać wyprowadzone.
Na przykład:
echo "foo bar <foo> bla 1 2 3.4" | cut -d " " -f 6-7
Daje wynik:
2 3.4
-d ustawia separator
-f wybiera zakres 'pól' do wyprowadzenia, w tym przypadku jest to fragment od 6 do 7 oryginalnego ciągu. Możesz również określić zakres w postaci listy, na przykład
6,7
.źródło
awk '{ print $2" "$6 }'
cut -d " " -f 2,6
Zgadzam się z @kent, że dobrze się do tego nadaje
grep -o
. Jeśli chcesz wyodrębnić grupę we wzorcu, możesz to zrobić za pomocą drugiego grepa.# To extract \1 from /xx([0-9]+)yy/ $ echo "aa678bb xx123yy xx4yy aa42 aa9bb" | grep -Eo 'xx[0-9]+yy' | grep -Eo '[0-9]+' 123 4 # To extract \1 from /a([0-9]+)b/ $ echo "aa678bb xx123yy xx4yy aa42 aa9bb" | grep -Eo 'a[0-9]+b' | grep -Eo '[0-9]+' 678 9
źródło