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


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

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

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

awk '{ printf ; }'

или sed

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

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

5 275

5 ответов:

попробуй:

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

С tr man page:

-s, --squeeze-repeats   replace each input sequence of a repeated character
                        that is listed in SET1 with a single occurrence
                        of that character

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

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

tr | вырезать

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

awk

awk '{print }' file

Баш

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

sed

sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*//' 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

$ 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 }' 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

sed

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

$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*//' a
1
2
3
4

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

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

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

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

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

$ cuts 2 text.txt
2
2

cuts поддержка:

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

и многое другое. Ни один из которых не предусмотрен стандартом cut.

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

исходный код и документацию (свободное программное обеспечение): http://arielf.github.io/cuts/

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

perl -lane 'print $F[3]' text.txt
на @F autosplit массив начинается с индекса $F[0] в то время как awk поля начинаются с

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