Присоединение Unix дает противоречивые результаты в Windows 7

Имейте набор данных, в котором максимальное количество записей в одном файле составляет ~ 130 000.

Вот подмножество первого файла, 1.txt:

CID|UID|Key|sis_URL
1|D000108|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779
1|D000108|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622
1|D000644|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779
1|D000644|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622
1|D002331|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779
1|D002331|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622
11|C024565|WSLDOOZREJYCGB|http://sis.gov/regno=0000107062
13|C009947|PBKONEOXTCPAFI|http://sis.gov/regno=0000120821
13|C009947|PBKONEOXTCPAFI|http://sis.gov/regno=0063697187

Вот подмножество второго файла, 2.txt:

CID|bro_URL
11|http://bro.gov/nmbr=0149
13|http://bro.gov/nmbr=0119

Я использую gnuwin32 под Windows 7, 64-разрядная версия с 8 ГБ памяти; поэтому необходимо использовать двойные кавычки для окон. Команда соединения:

join -t"|" -1 1 -2 1 -a1 -a2 -e "NULL" -o "0,1.2,1.3,1.4,2.2" 1.txt 2.txt > 3_.txt

Вот выходной файл 3.txt.

CID|UID|Key|sis_URL|bro_URL
1|D000108|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779|NULL
1|D000108|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622|NULL
1|D000644|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779|NULL
1|D000644|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622|NULL
1|D002331|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779|NULL
1|D002331|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622|NULL
11|NULL|NULL|NULL|http://bro.gov/nmbr=0149
13|NULL|NULL|NULL|http://bro.gov/nmbr=0119
11|C024565|WSLDOOZREJYCGB|http://sis.gov/regno=0000107062|NULL
13|C009947|PBKONEOXTCPAFI|http://sis.gov/regno=0000120821|NULL
13|C009947|PBKONEOXTCPAFI|http://sis.gov/regno=0063697187|NULL

Для CID:11 и CID:13 я ожидаю:

11|C024565|WSLDOOZREJYCGB|http://sis.gov/regno=0000107062|http://bro.gov/nmbr=0149
13|C009947|PBKONEOXTCPAFI|http://sis.gov/regno=0000120821|http://bro.gov/nmbr=0119
13|C009947|PBKONEOXTCPAFI|http://sis.gov/regno=0063697187|http://bro.gov/nmbr=0119

Почему join в CID:11 и CID:13 не работает?

Примечание. Прежде чем публиковать этот вопрос, я запустил приведенное выше подмножество и получил правильные результаты. Когда я запускаю полный набор, я получаю неправильный результат (подмножество, показанное здесь).

Есть идеи, почему? Любая рекомендуемая альтернатива?

Когда я завершу процесс join, моя итоговая таблица будет состоять из 15 столбцов. Но я уже застрял в столбце 4.

Любое предлагаемое обходное решение, такое как awk?


person Jay Gray    schedule 28.12.2013    source источник
comment
Спасибо - awk-скрипт дал правильный результат. Имейте три вопроса. (a) изначально я запускал команду с другим порядком файлов (1.txt 2.txt). Это не сработало. Объясните, пожалуйста, почему вы заказали файлы 2.txt 1.txt. (b) Не могли бы вы предоставить немного документации, чтобы я мог масштабировать этот подход, чтобы повторить процесс awk еще 10 раз по мере постепенного создания конечного результата? (c) Как ввести NULL, если поле в строке пустое?   -  person Jay Gray    schedule 28.12.2013
comment
Пожалуйста. Я посмотрю на это. Кстати, вы должны дать этот комментарий ниже моего ответа, а не здесь, на ваш вопрос.   -  person Håkon Hægland    schedule 28.12.2013
comment
При запуске в Unix (в частности, в Mac OS X) команда join для ваших данных дает ожидаемый ответ как с строками заголовков в данных, так и без них. Однако команда join ожидает, что данные в файлах будут отсортированы, и могут происходить забавные вещи, когда входные данные не отсортированы, а строки заголовков означают, что данные не отсортированы. Один из моментов, который вам нужно проверить, — это работает ли удаление заголовков для вас в Windows. Однако до сих пор не очевидно, как это может пойти не так.   -  person Jonathan Leffler    schedule 28.12.2013
comment
@Jonathan Leffler Спасибо за совет. Я знаю, как сортировать данные в ключевом поле, и делал это в мастер-файлах. Но поскольку файлы большие, я мог поместить здесь только подмножество. Соединение подмножества работает; у главного соединения есть проблема выше.   -  person Jay Gray    schedule 28.12.2013


Ответы (1)


Вы можете попробовать следующую команду:

awk -f a.awk 2.txt 1.txt > 3.txt

где a.awk это:

BEGIN { FS=OFS="|" }
NR==FNR{
    a[$1]=$2
    next
}
{
    if ($1 in a)
        $(NF+1)=a[$1]
    else 
        $(NF+1)="NULL"
    print
}

с выходом:

CID|UID|Key|sis_URL|bro_URL
1|D000108|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779
1|D000108|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622
1|D000644|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779
1|D000644|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622
1|D002331|RDHQFKQIGNGIED|http://sis.gov/regno=0000870779
1|D002331|RDHQFKQIGNGIED|http://sis.gov/regno=0014992622
11|C024565|WSLDOOZREJYCGB|http://sis.gov/regno=0000107062|http://bro.gov/nmbr=0149
13|C009947|PBKONEOXTCPAFI|http://sis.gov/regno=0000120821|http://bro.gov/nmbr=0119
13|C009947|PBKONEOXTCPAFI|http://sis.gov/regno=0063697187|http://bro.gov/nmbr=0119

Пояснение

  • Считываем данные из 2.txt в ассоциативный массив a
  • Тест NR==FNR используется для сопоставления только первого файла в командной строке, то есть файла 2.txt.
  • Оператор next важен для того, чтобы следующие правила не выполнялись для 2.txt
  • Второе правило (содержащее тест if) затем выполняется только для 1.txt, но информация из 2.txt по-прежнему доступна через массив a
  • Если первое поле соответствует полю в первом столбце в 2.txt, то есть: if ($1 in a), то мы вставляем это значение в конец строки (NF — это количество полей (то есть: столбцов), считанных из 1.txt)
  • Если совпадения нет, вставляем строку "NULL"
person Håkon Hægland    schedule 28.12.2013
comment
Спасибо - awk-скрипт дал правильный результат. Имейте три вопроса. (a) изначально я запускал команду с другим порядком файлов (1.txt 2.txt). Это не сработало. Объясните, пожалуйста, почему вы заказали файлы 2.txt 1.txt. (b) Не могли бы вы предоставить немного документации, чтобы я мог масштабировать этот подход, чтобы повторить процесс awk еще 10 раз по мере постепенного создания конечного результата? (c) Как ввести NULL, если поле в строке пустое? Еще раз спасибо за быстрое и эффективное решение. Я отмечу ваше решение как ответ. - person Jay Gray; 28.12.2013
comment
@JayGray Что вы подразумеваете под вставкой поля NULL? Вы имеете в виду в конце каждой строки, которая не соответствует строке в 1.txt? - person Håkon Hægland; 28.12.2013
comment
@JayGray Порядок файлов в командной строке важен для awk.. Он начинается с первого аргумента (самого левого) и обрабатывает этот файл первым.. Поэтому программа не будет работать, если вы измените порядок.. - person Håkon Hægland; 28.12.2013
comment
При использовании соединения unix я использую флаг -e, а затем использую NULL в качестве значения, когда нет совпадения для соединения. Например, в 3.txt соединение вставило NULL для CID:1, потому что нет совпадения с 2.txt. Я использую флаг -e, чтобы поместить значение в ячейку, которая в противном случае пуста. Надеясь использовать аналогичную функцию в вашем скрипте awk. - person Jay Gray; 28.12.2013
comment
Еще раз спасибо, Хокон. Теперь у меня есть шанс сделать эту работу сегодня :-› - person Jay Gray; 28.12.2013