Вопрос или проблема
Вот пример:
$ cat file1
hello
there
$ cat file2
some,very,long,line,hello,csv
some,very,long,line,nope,csv
$ join -t, -1 1 -2 5 file1 file2
hello,some,very,long,line,csv
Это работает как задокументировано: объединенное поле вытаскивается налево, остальные поля выводятся.
Но я хочу сохранить порядок столбцов CSV (file2). Я могу вывести CSV в неизменном виде с помощью этой команды, которая явно перечисляет номера полей CSV:
join -t, -1 1 -2 5 -o $(head -n1 file2 | awk -F, '{print NF}' | xargs seq | sed 's/^/2./' | paste -d, -s) file1 file2
И это выводит:
some,very,long,line,hello,csv
Я думал, что именно для этого в join
есть формат auto
. Вот что говорит страница man для join
о -o FORMAT
:
Если FORMAT — это ключевое слово ‘auto’, то первая строка каждого файла определяет количество полей, выводимых для каждой строки.
Тем не менее, я не знаю, что это означает или как мне следует использовать формат auto
.
Я пробовал это, но не получил ничего другого, чем раньше:
$ join -t, -1 1 -2 5 -o auto file1 file2
hello,some,very,long,line,csv
Наивная интерпретация была бы таковой: я должен перечислить необходимые поля как первую строку каждого файла, но это тоже неверно.
Итак, мой вопрос: для чего нужен auto
, и как мне его использовать? Могу ли я использовать его, чтобы сохранить порядок столбцов входного CSV?
Лично я считаю, что вывод по умолчанию от join
такой, как я и ожидал (сначала поля объединения, затем остальные поля из file1, затем остальные поля из file2). Я не знаю, какой другой вывод имел бы смысл в общем случае объединения 2 файлов по ключевым полям (оставить ключевые поля в позиции file1, в позиции file2 или что-то еще? Будут ли неключевые поля, объединенные из обоих файлов, в алфавитном порядке или что-то еще?) и всегда есть -o
, если вы предпочитаете какой-то другой формат, отличающийся от стандартного.
Относительно того, что означает -o auto
, как вы привели:
Если FORMAT — это ключевое слово ‘auto’, то первая строка каждого файла определяет количество полей, выводимых для каждой строки.
Таким образом, если первая строка второго файла содержала 6 полей, а вторая строка 9 полей, то 6 полей этого файла будут напечатаны для каждой выходной строки, например:
$ cat file3
some,very,long,line,hello,csv
other,kina,long,line,hello,csv,jpeg,pdf,foobar
some,very,long,line,nope,csv
без -o auto
:
$ join -t, -1 1 -2 5 file1 file3
hello,some,very,long,line,csv
hello,other,kina,long,line,csv,jpeg,pdf,foobar
в сравнении с -o auto
:
$ join -t, -1 1 -2 5 -o auto file1 file3
hello,some,very,long,line,csv
hello,other,kina,long,line,csv
Сказав это, join
все равно не был бы самым очевидным выбором для того, что вы пытаетесь сделать (вывести строки из file2, которые имеют значение ключа, хранящееся в file1). Например, используя любой awk
в любой оболочке на всех системах Unix, это было бы просто:
$ awk -F, 'NR==FNR{k[$1]; next} $5 in k' file1 file2
some,very,long,line,hello,csv
$ awk -F, 'NR==FNR{k[$1]; next} $5 in k' file1 file3
some,very,long,line,hello,csv
other,kina,long,line,hello,csv,jpeg,pdf,foobar
Ответ или решение
Команда join
в Unix/Linux предназначена для объединения строк из двух файлов на основе общих ключевых полей. При использовании опции формата -o
, вы можете настраивать, какие поля включать в вывод. Опция -o auto
имеет свои особенности, которые необходимо правильно интерпретировать для достижения желаемого результата.
Как работает автоформат -o auto
При использовании ключевого слова auto
для опции -o
, команда join
будет использовать количество полей, определяемое первой строкой в каждом из файлов. Это означает, что join
будет подстраивать вывод в зависимости от структуры этих строк.
Пример использования
Рассмотрим два файла:
Файл file1
:
hello
there
Файл file2
:
some,very,long,line,hello,csv
some,very,long,line,nope,csv
Если выполнить команду:
join -t, -1 1 -2 5 -o auto file1 file2
Вывод будет:
hello,some,very,long,line,csv
Результаты команды с -o auto
В данном случае, join
выводит первое ключевое поле из file1
(содержимое hello
), затем оно добавляет все соответствующие поля из file2
, определяемые в порядке, в котором они указаны. Однако, если вам нужно сохранить порядок полей из file2
в выводе, используйте явное указание полей, как в вашем примере с использованием awk
.
Как обеспечить нужный порядок колонок
Для достижения желаемого вывода с сохранением порядка колонок из file2
, вы можете воспользоваться командой awk
, как уже указано в вашем примере:
awk -F, 'NR==FNR{k[$1]; next} $5 in k' file1 file2
Эта команда позволяет находить строки из file2
, которые содержат ключи из file1
, сохраняя оригинальный порядок полей в выходных данных.
Заключение
Таким образом, использование -o auto
может быть не совсем интуитивным, поскольку оно работает на основе количества полей в первой строке файлов. Если ваша задача заключается в сохранении оригинального порядка полей из одного из файлов, то прямое указание необходимых полей с помощью -o
или использование awk
будет более подходящим решением. Это даст вам возможность четко управлять форматом выводимых данных в соответствии с вашими требованиями.