Почему awk неправильно определяет границы данных, разделённых табуляцией
Следующая команда вместо ожидаемого третьего столбца вернёт пустой результат:
echo '1 2 3 4 5 6' | awk -F'\t' '{ print $3 }'
В команде вместо стандартного FS (Input field separator, разделитесь полей входных данных), которым по умолчанию является пробел, опцией -F'\t' установлен новый разделитесь, в качестве которого указан «\t», что означает символ табуляции.
Проблема предыдущей команды в том, что во входных данных поля на самом деле не разделены символами табуляции, а разделены несколькими пробелами.
То есть использовании опции -F не нужно в предыдущей команде:
echo '1 2 3 4 5 6' | awk '{ print $3 }'
3
Несмотря на то, что данные разделены несколькими пробелами, указывать это с опцией -F не нужно, поскольку она правильно истолковывает ввод. По умолчанию разделителем полей в awk служит один или больше пробелов (пробельные символы или символ табуляции), что соответствует [ \t]+ или если использовать posix классы [[:blank:]]+
Именно поэтому даже если данные на самом деле разделены табуляцией, команда awk обрабатывает их правильно:
echo '1 2 3 4' | awk '{ print $3 }'
3
В этом случае опция -F'\t' работает как и ожидается:
echo '1 2 3 4' | awk -F'\t' '{ print $3 }'
3
Нужно отметить, что разделитель полей в awk является регулярным выражением. Поэтому идущие подряд повторяющиеся символы, выбранные в качестве разделителей столбцов, трактуются как единый разделитесь между двумя смежными полями.
Чтобы проверить, какие именно непечатные символы присутствуют во вводимых данных, используйте cat -A. Например:
echo '1 2 3 4' | cat -A
1M-bM-^PM-^A^IM-oM-?M-=2^I3 4$
Как сделать так, чтобы awk выводила поля разделяя их табуляцией
Следующая команда выведет третью и четвёртую колонку, разделяя их пробелом:
echo '1 2 3 4 5' | awk '{ print $3,$4 }'
3 4
Если вы хотите, чтобы выводимые данные разделялись табуляцией (или любым другим символом), то его нужно установить в качестве значения OFS (output field separator, разделитесь выходных полей). Например:
echo '1 2 3 4 5' | awk 'BEGIN {OFS="\t"}; { print $2,$3 }'
2 3
OFS вставляется между полями, перечисленными через запятую, то есть следующая команда не выведет табуляции между полями (и даже не выведет пробел):
echo '1 2 3 4 5' | awk 'BEGIN {OFS="\t"}; { print $2 $3 }'
23
Кроме изменения значения OFS (output field separator, разделитесь выходных полей) вы можете указать символ табуляции в шаблоне вывода. Например, следующая команда для разделения второго и третьего поля будет использовать стандартный OFS (то есть пробел), а между третьей и четвёртой колонкой будет вставлен знак табуляции:
echo '1 2 3 4 5' | awk '{ print $2,$3"\t"$4 }'
2 3 4
Смотрите также: Уроки по Awk






