Jak używać wycinania, aby rozdzielić wiele białych spacji?

23

Chciałbym uzyskać ostatnią kolumnę tej próbki:

[  3]  1.0- 2.0 sec  1.00 MBytes  8.39 Mbits/sec
[  3]  2.0- 3.0 sec   768 KBytes  6.29 Mbits/sec
[  3]  3.0- 4.0 sec   512 KBytes  4.19 Mbits/sec
[  3]  4.0- 5.0 sec   256 KBytes  2.10 Mbits/sec
...

Jeśli użyję

cut -d\  -f 13

dostaję

Mbits/sec
6.29
4.19
2.10

ponieważ czasami są między nimi dodatkowe spacje.

rubo77
źródło
Ostatnią kolumną jest Mbits/sec, czy tego właśnie chcesz, czy 2 ostatnie kolumny?
terdon
1
Chcę tylko zdobyć drugą ostatnią kolumnę, tylko liczby
rubo77

Odpowiedzi:

17

Aby dosłownie odpowiedzieć na twoje pytanie:

sed 's/   */:/g' | cut -d : -f 5

lub

awk -F '  +' '{print $5}'

Ale tak się nie stanie, jeśli liczba w nawiasach osiągnie 10 itd. Jeśli interesują Cię tylko liczby, możesz usunąć wszystko inne.

sed 's/[^.0-9][^.0-9]*/:/g' | cut -d : -f 6
Gilles „SO- przestań być zły”
źródło
tak, pewnie tylko liczby, ale tylko twój trzeci przykład działa poprawnie
rubo77
@ rubo77 Działa dla mnie. Dwa pierwsze przykłady robią dokładnie to, o co prosisz w tytule. A może chciałeś też zdjąć urządzenie? W takim przypadku dodaj | sed 's/ .*//'na końcu pierwszych dwóch przykładów. Oczywiście istnieje wiele innych sposobów, aby to zrobić.
Gilles „SO- przestań być zły”
nieco krótszy z +zamiast *: cat test | sed 's / [^. 0-9] \ + /: / g' | cut -d: -f 6
rubo77
@ rubo77 Jeśli twój sed to obsługuje, to znaczy. Jest obsługiwany przez GNU i BusyBox, ale nie przez np. BSD lub Solaris. POSIX określa, +a ?w ERE ale pozostawia \+i \?BRE niezdefiniowane.
Gilles „SO- przestań być zły”
22

Jeśli użyjemy trpolecenia wraz z opcją ściśnięcia ( -sflaga), aby przekonwertować wszystkie kolejne spacje na jedną spację, a następnie wykonać cutoperację spacją jako separatorem - możemy uzyskać dostęp do wymaganej kolumny niosącej liczby.

Zobacz poniższy fragment kodu:

cat file | tr -s ' ' | cut -d ' ' -f 8

Wald Schilfrohr
źródło
4
Ta odpowiedź powinna być wyższa; jest to zdecydowanie najprostsze i najbardziej czytelne rozwiązanie.
Luke Davis,
5

Wszystkie te polecenia wypisują ostatnią kolumnę pliku oddzielonego spacjami:

  • awk '{print $NF}' file

    w awk, NFjest liczbą pól i $NFjest ostatnim polem.

  • perl -lane 'print $F[$#F]' file

    -adzieli plik z białymi spacjami na tablicę @F, $#Fjest liczbą elementów w tablicy, więc $F[$#F]jest ostatnim elementem. Te -nśrodki odczytać plik podany w wierszu poleceń i zastosować skrypt zapadają -ena każdej linii. -lpo prostu dodaje znak nowej linii ( \n) do każdej printinstrukcji.

  • sed 's/.* //g'

    proste wyrażenie regularne, które dopasowuje wszystko do ostatniej spacji i usuwa je, pozostawiając tylko ostatnią kolumnę.

  • rev file | cut -d' ' -f 1 | rev

    revodwraca dane wyjściowe, więc ostatnie pole jest pierwsze, cutz miejscem na separator, aby je wydrukować i revprzywrócić normalny tekst. To nie zadziała, jeśli masz kolejne białe znaki .

Na podstawie twoich danych wejściowych domyślam się, że tak naprawdę nie chcesz ostatniej kolumny, ale przedostatniej lub dwóch ostatnich. W takim przypadku użyj ich do wydrukowania ostatnich 2 ( 8.39 Mbits/sec):

awk '{print $(NF-1),$NF}' file 
perl -lane 'print "$F[$#F-1] $F[$#F]"' file 
sed 's/.* \(.* .*\)/\1/' file 
rev file | cut -d' ' -f 1,2 | rev

i te, aby wydrukować przedostatni ( 8.39):

awk '{print $(NF-1)}' file 
perl -lane 'print $F[$#F-1]' file 
sed 's/.* \(.*\) .*/\1/' file 
rev file | cut -d' ' -f 2 | rev
terdon
źródło
4

Nie można oddzielić wielokrotnego występowania białych znaków za pomocą cutinstrukcji:

Pola wyjściowe są oddzielone pojedynczym wystąpieniem znaku ogranicznika pola.

chyba że tekst jest oddzielony tą samą kwotą lub użyjesz go trdo usunięcia ich nadmiaru.

W inny sposób wykorzystywać alternatywne narzędzia, takie jak awk, sedlub ex.

Na przykład:

ex -s +'%norm $2Bd0' +%p +q! foo.txt

Wymień +q!się -cwq, aby zapisać zmiany w miejscu.

kenorb
źródło
0

Użyj jednego linijki Perla:

perl -lane 'print $F[-2]' input_file

Wyjaśnienie:

Opcja -epowoduje, że interpreter perla szuka wbudowanego skryptu zamiast w pliku.

Opcja -npowoduje, że wejście (plik lub STDIN z potoku) jest odczytywane linia po linii.

Opcja -lusuwa separator rekordów wejściowych (domyślnie zależny od systemu operacyjnego, nowa linia w systemie UNIX) po przeczytaniu linii i dodaje ją na końcu do każdegoprint

Opcja -apowoduje podział każdej linii wejściowej na białe znaki na tablicę @Fi $F[-2]jest drugim elementem liczącym od końca, którym jest pole, które chcesz. Możesz także użyć $F[$#F-1], gdzie $#Fjest ostatnim indeksem tablicy @F, który jest nieco mniej czytelny.

Timur Shtatland
źródło