Как использовать вырезание для разделения на несколько пробелов?

23

Я хотел бы получить последний столбец этого образца:

[  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
...

Если я использую

cut -d\  -f 13

я получил

Mbits/sec
6.29
4.19
2.10

потому что иногда есть дополнительные пробелы между ними.

rubo77
источник
Последний столбец - Mbits/secэто то, что вы хотите, или 2 последних столбца?
Terdon
1
Я только хочу получить 2-ую последнюю колонку, только цифры
rubo77

Ответы:

17

Чтобы ответить на ваш вопрос буквально:

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

или

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

Но этого не произойдет, если число в скобках достигнет 10 и т. Д. Если вас интересуют только цифры, вы можете удалить все остальное.

sed 's/[^.0-9][^.0-9]*/:/g' | cut -d : -f 6
Жиль "ТАК - перестань быть злым"
источник
да, конечно, только цифры, но только ваш третий пример работает правильно
rubo77
@ rubo77 У меня работает. Первые два примера делают именно то, что вы просите в заголовке. Или вы хотели снять устройство? В этом случае добавьте | sed 's/ .*//'в конце первых двух примеров. Конечно, есть много других способов сделать это.
Жиль "ТАК - перестань быть злым"
немного короче с +вместо *: кошка тест | sed 's / [^. 0-9] \ + /: / g' | cut -d: -f 6
rubo77
@ rubo77 Если ваш sed это поддерживает, то есть. Он поддерживается GNU и BusyBox, но не поддерживается, например, BSD или Solaris. POSIX указывает +и ?на ERE, но оставляет, \+и \?на BRE не определено.
Жиль "ТАК - перестань быть злым"
22

Если мы используем trкоманду вместе с опцией ( флагом) squeeze-s для преобразования всех нескольких последовательных пробелов в один пробел, а затем выполняем cutоперацию с пробелом в качестве разделителя - мы можем получить доступ к необходимому столбцу, содержащему числа.

Обратитесь к приведенному ниже коду:

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

Вальд Шильфрор
источник
4
Этот ответ должен быть выше; это , безусловно, самое простое и удобочитаемое решение.
Люк Дэвис
5

Все эти команды будут печатать последний столбец файла, разделенного пробелами:

  • awk '{print $NF}' file

    in awk, NFчисло полей и $NFпоследнее поле.

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

    -aразбивает файл на пробел в массив @F, $#Fэто количество элементов в массиве, так же $F[$#F]как и последний элемент. В -nсредстве чтение файла , заданный в командной строке и применить скрипт передается с -eкаждой строкой. -lпросто добавляет символ новой строки ( \n) к каждому printутверждению.

  • sed 's/.* //g'

    простое регулярное выражение, которое сопоставляет все с последним пробелом и удаляет его, оставляя только последний столбец.

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

    revинвертирует вывод, так что последнее поле является первым, cutс пробелом для его печати и revвозврата текста в нормальное состояние. Это не сработает, если у вас есть последовательные пробелы .

Исходя из вашего ввода, я предполагаю, что вы на самом деле не хотите последний столбец, а предпоследний или два последних. В этом случае используйте их, чтобы напечатать последние 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

и эти, чтобы напечатать предпоследний ( 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
Тердон
источник
4

Вы не можете отделить множественные вхождения пробелов, используя cutв соответствии с руководством:

Выходные поля разделены одним вхождением символа разделителя полей.

если текст не разделен на ту же сумму или вы используете trдля удаления избытка их.

В противном случае используйте альтернативные инструменты, такие как awk, sedили ex.

Например:

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

Замените +q!на, -cwqчтобы сохранить изменения на месте.

kenorb
источник
0

Используйте perl one-liner примерно так:

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

Объяснение:

Опция -eзаставляет интерпретатор perl искать скрипт внутри строки, а не в файле.

Опция -nзаставляет ввод (файл или STDIN из канала) читать построчно.

Опция -lудаляет разделитель входной записи (зависит от ОС, по умолчанию - новая строка в UNIX) после чтения строки и добавляет его в конце к каждомуprint

Опция -aзаставляет каждую входную строку разбиваться на пустое пространство на массив @F, и $F[-2]является вторым элементом, считая с конца, то есть поле, которое вы хотите. Вы также можете использовать $F[$#F-1], где $#Fпоследний индекс массива @F, который немного менее читабелен.

Тимур Штатланд
источник