Ответ 1
Пытаться:
tr -s ' ' <text.txt | cut -d ' ' -f4
Со страницы руководства tr
:
-s, --squeeze-repeats replace each input sequence of a repeated character that is listed in SET1 with a single occurrence of that character
Я пытаюсь извлечь определенное (четвертое) поле из текстового потока, скорректированного по пространству. Я пытаюсь использовать команду cut
следующим образом:
cat text.txt | cut -d " " -f 4
К сожалению, cut
не обрабатывает несколько пробелов как один разделитель. Я мог бы пропустить через awk
awk '{ printf $4; }'
или sed
sed -E "s/[[:space:]]+/ /g"
чтобы свернуть пробелы, но я хотел бы знать, есть ли способ иметь дело с cut
и несколькими разделителями изначально?
Пытаться:
tr -s ' ' <text.txt | cut -d ' ' -f4
Со страницы руководства tr
:
-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
, чтобы сжать пробелы, как показывает kev answer.
Позвольте мне, однако, пройти все возможные комбинации для будущих читателей. Объяснения приведены в разделе "Тест".
tr -s ' ' < file | cut -d' ' -f4
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
$ 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 '{print $4}' a
1
2
3
4
Это последовательно читает поля. Используя _
, мы указываем, что это переменная throwaway как "мусорная переменная", чтобы игнорировать эти поля. Таким образом, мы сохраняем $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
После разочарования слишком большим количеством ограничений cut
, я написал свою собственную замену, которую я назвал cuts
для "разрезания стероидов".
cuts обеспечивает то, что, вероятно, является самым минималистским решением этой и многих других проблем, связанных с вырезанием/вставкой.
Один пример из многих, рассматривающих этот конкретный вопрос:
$ cat text.txt
0 1 2 3
0 1 2 3 4
$ cuts 2 text.txt
2
2
cuts
поддерживает:
paste
отдельно)и многое другое. Ни один из них не предоставляется стандартным cut
.
Смотрите также: fooobar.com/questions/28564/...
Источник и документация (бесплатное программное обеспечение): http://arielf.github.io/cuts/
Этот однострочный Perl показывает, насколько тесно Perl связан с awk:
perl -lane 'print $F[3]' text.txt
Однако массив autosplit @F
начинается с индекса $F[0]
, тогда как awk-поля начинаются с $1
С версиями cut
я знаю, нет, это невозможно. cut
в первую очередь полезен для разбора файлов, где разделитель не является пробелом (например, /etc/passwd
) и имеет фиксированное количество полей. Два разделителя в строке означают пустое поле, и это тоже относится к пробелу.