Как заставить команду 'cut' обрабатывать те же последовательные разделители, что и один?

309

Я пытаюсь извлечь определенное (четвертое) поле из текстового потока, скорректированного по столбцам. Я пытаюсь использовать cutкоманду следующим образом:

cat text.txt | cut -d " " -f 4

К сожалению, cutне рассматривает несколько пробелов как один разделитель. Я мог бы пройти через awk

awk '{ printf $4; }'

или сед

sed -E "s/[[:space:]]+/ /g"

свернуть пробелы, но я хотел бы знать, есть ли способ иметь дело с cutнесколькими разделителями изначально?

mbaitoff
источник
12
AWK - это путь.
Приостановлено до дальнейшего уведомления.

Ответы:

546

Пытаться:

tr -s ' ' <text.txt | cut -d ' ' -f4

Со trстраницы руководства :

-s, --squeeze-repeat повторяет каждую входную последовательность повторяющегося символа
                        который указан в SET1 с одним вхождением
                        этого персонажа
кэв
источник
24
Нет необходимости catздесь. Вы можете перейти < text.txtнепосредственно к tr. en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat
Ариэльф
1
Не уверен, что это немного проще, но вы собираетесь объединить, вы можете отказаться от вырезок -dи переводить сразу из нескольких символов в табуляцию. Например: я пришел сюда в поисках способа автоматического экспорта моего дисплея:who am i | tr -s ' ()' '\t' | cut -f5
Leo
Это не удаляет начальные / конечные пробелы (которые могут или не могут быть желательны, но обычно нет), в отличие от решения awk. Решение awk также намного более читабельно и менее многословно.
n.caillou
-1 ПРЕДУПРЕЖДЕНИЕ: ЭТО НЕ ТО ЖЕ ВРЕМЯ, КАК ЛЕЧИТЬ ПОСЛЕДОВАТЕЛЬНЫЕ РАЗДЕЛИТЕЛИ, КАК ОДИН. Сравните echo "a b c" | cut -d " " -f2-,echo "a b c" | tr -s " " | cut -d " " -f2-
user541686
96

Как вы прокомментируете в своем вопросе, awkэто действительно путь. Использовать cutможно вместе с тем, tr -sчтобы сжать пробелы, как показывает ответ Кева.

Позвольте мне, однако, пройти через все возможные комбинации для будущих читателей. Пояснения в разделе Тест.

tr | резать

tr -s ' ' < file | cut -d' ' -f4

AWK

awk '{print $4}' file

удар

while read -r _ _ _ myfield _
do
   echo "forth field: $myfield"
done < file

СЭД

sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' file

тесты

Учитывая этот файл, давайте проверим команды:

$ cat a
this   is    line     1 more text
this      is line    2     more text
this    is line 3     more text
this is   line 4            more    text

tr | резать

$ cut -d' ' -f4 a
is
                        # it does not show what we want!


$ tr -s ' ' < a | cut -d' ' -f4
1
2                       # this makes it!
3
4
$

AWK

$ awk '{print $4}' a
1
2
3
4

удар

Это читает поля последовательно. Используя, _мы указываем, что это одноразовая переменная как «нежелательная переменная», чтобы игнорировать эти поля. Таким образом, мы сохраняем $myfieldв файле 4-е поле, независимо от того, что между ними.

$ while read -r _ _ _ a _; do echo "4th field: $a"; done < a
4th field: 1
4th field: 2
4th field: 3
4th field: 4

СЭД

Это ловит три группы пробелов и без пробелов с ([^ ]*[ ]*){3}. Затем он захватывает все, что приходит до пробела в качестве 4-го поля, на котором он наконец напечатан \1.

$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4
Федорки "ТАК прекратить вредить"
источник
2
awkОн не только элегантен и прост, но и включен в VMware ESXi, где trотсутствует.
user121391
2
@ user121391 еще одна причина для использования awk!
Федорки "ТАК прекрати вредить"
@fedorqui Я никогда не слышал о подчеркивании как о «нежелательной переменной». Можете ли вы предоставить более подробную информацию / ссылку на это?
BryKKan
1
@BryKKan Я узнал об этом из книги Грега. Как я могу прочитать файл (поток данных, переменную) построчно (и / или поле за полем)? : Некоторые люди используют переменную _ одноразовые в качестве «нежелательной переменной» игнорировать поля. Его (или любую другую переменную) также можно использовать более одного раза в одной readкоманде, если нам все равно, что с ней происходит . Это может быть что угодно, просто это как-то стало стандартом вместо junk_varили whatever:)
fedorqui 'ТАК ХОТИТЕ вредить'
25

самое короткое / самое дружелюбное решение

Разочаровавшись в слишком большом количестве ограничений cut, я написал свою собственную замену, которую я призвал cuts«сократить на стероидах».

порезы обеспечивает то, что, вероятно, является наиболее минималистичным решением этой и многих других проблем, связанных с вырезанием / вставкой

Один из многих примеров, касающихся этого конкретного вопроса:

$ cat text.txt
0   1        2 3
0 1          2   3 4

$ cuts 2 text.txt
2
2

cuts опоры:

  • автоопределение наиболее распространенных разделителей полей в файлах (+ возможность отмены значений по умолчанию)
  • разделители multi-char, mixed-char и regex
  • извлечение столбцов из нескольких файлов со смешанными разделителями
  • смещения от конца строки (с использованием отрицательных чисел) в дополнение к началу строки
  • автоматическое вставка столбцов рядом друг с другом (не нужно вызывать pasteотдельно)
  • поддержка переупорядочения полей
  • файл конфигурации, в котором пользователи могут изменять свои личные настройки
  • большой акцент на удобстве использования и минималистском наборе текста

и многое другое. Ничего из этого не предусмотрено стандартом cut.

Смотрите также: https://stackoverflow.com/a/24543231/1296044

Источник и документация (бесплатное программное обеспечение): http://arielf.github.io/cuts/

arielf
источник
4

Этот однострочный текст Perl показывает, насколько тесно Perl связан с awk:

perl -lane 'print $F[3]' text.txt

Однако @Fмассив autosplit начинается с индекса, $F[0]а поля awk начинаются с$1

Крис Кокнат
источник
3

С версиями, о которых cutя знаю, нет, это невозможно. cutпрежде всего полезен для разбора файлов, где разделитель не является пробелом (например /etc/passwd) и имеет фиксированное количество полей. Два разделителя в строке означают пустое поле, и это также относится к пробелам.

Benoit
источник