Файл, разделенный вкладкой карты, со списком, использующим awk/sed/join

#awk #sed #grep

Вопрос:

У меня есть несколько больших файлов с двумя столбцами (разделенными табуляцией). Содержимое этих файлов выглядит следующим образом:

рабочий файл-1

 K00001 0.188
K00005 15.97
K00008 188.09
 

файл сопоставления

 K00001
K00002 
K00003
K00004
K00005
K00006 
K00007
K00008
 

диапазон файлов сопоставления составляет K00001 — K25804

Я хочу сопоставить свой working_file-1 с файлом сопоставления, чтобы результат выглядел так:

 K00001 0.188
K00002 
K00003
k00004
K00005 15.97
K00006 
K00007
k00008 188.09
 

Пробелы (K0 отсутствует в working_file) могут быть заполнены нулем (если это возможно) или могут быть оставлены пустыми.

До сих пор я пробовал эти коды, следуя другим аналогичным постам (но безуспешно).:

 awk 'NR==FNR {a[$1]  ; next} $1 in a' mapping file working_file-1 > output.file

grep -Fw -f mapping file working_file-1 > output.file
 

редактировать: вывод работы od -c1; карта od -c

 0000000   K   0   0   0   0   1  r  n   K   0   0   0   0   2  r  n
0000020   K   0   0   0   0   3  r  n   K   0   0   0   0   4  r  n
0000040   K   0   0   0   0   5  r  n   K   0   0   0   0   6  r  n
0000060   K   0   0   0   0   7  r  n   K   0   0   0   0   8  r  n
 

Комментарии:

1. sort -rf "mapping file" working_file-1 | awk '$1==p{next} !$2{$2=0} {p=$1} 1' | tac > output.file

2. Есть ли какое-то значение в сочетании строчных и прописных букв K? Является ли совпадение чувствительным к регистру или без учета регистра?

3. @JonathanLeffler извини. это все верхние case..my опечатка.

4. Должны ли K00087, K00105, K00118, K01206 отображаться в выходных данных для показанных входов? Появится ли каждое число в working_file-1 файле сопоставления? Оба входных файла расположены в порядке сортировки чисел Kxxxxx?

5. @jhnc. да. извините. отредактировано сейчас

Ответ №1:

Учитывая файл «карта», такой как:

 a
b
c
d
e
f
g
h
 

и файл «work1», такой как:

 a A
c C
g G
 

и желаемый вывод «merged1», такой как:

 a A
b
c C
d
e
f
g G
h
 

затем join можно выполнить объединение:

 join -1 1 -2 1 -a 1 -o 0,2.2 map work1 > merged1
 
  • -1 1 -2 1 присоединяется к первому (разделенному пробелами) полю каждого файла
  • -a 1 печатает строки из первого файла, даже если они непарные
  • -o 0,2.2 форматы вывода: поле соединения (первый столбец), разделитель (пробел), затем второе поле второго файла

Чтобы вместо этого создать «merged2», как:

 a A
b 0
c C
d 0
e 0
f 0
g G
h 0
 

добавьте -e опцию:

 join -1 1 -2 1 -a 1 -e 0 -o 0,2.2 map work1 > merged2
 

Если в «work2» поля разделены символом, отличным от одного пробела, используйте эту -t опцию.

Например, с «work2» с использованием одного разделителя табуляции, например:

 a   A
c   C
g   G
 

(примечание: stackoverflow отображает это с пробелами вместо одной вкладки), затем с помощью оболочки POSIX используйте -t ' ' (т. Е. ВКЛАДКА ЦИТАТА ЦИТАТА — может потребоваться ввести как: 'CTRL-VTAB'если оболочка выполняет завершение истории):

 join -t '   ' -1 1 -2 1 -a 1 -e 0 -o 0,2.2 map work2 >merged3
 

или с помощью bash, -t $'t' вместо этого возможно использование:

 join -t 

чтобы создать "merged3", как:

 a   A
b   0
c   C
d   0
e   0
f   0
g   G
h   0
 

(примечание: снова stackoverflow отображает вкладку в виде пробелов)

Комментарии:

1. Действительно спасибо, что так красиво все изложил. но почему-то это не сработало. с помощью join -1 1 -2 1 -a 1 -e 0 -o 0,2.2 работа с картой 1 > слияние2 вывод-K00001 K00002 K00003 .... с соединением -t $'t' -1 1 -2 1 -a 1 -e 0 -o 0,2.2 работа с картой 2 >>объединение3 вывод-K00001 0 K00002 0 K00003 0 .....

2. @Shail какую ОС вы используете? Возьмите ваши новые примеры из вашего вопроса и запустите команду join - это работает? Если нет, запустите od -c work1; od -c map новые файлы, которые вы только что создали, и добавьте выходные данные в свой вопрос. Если это работает, попробуйте od -c realwork | less или что-то в вашем реальном файле и проверьте, соответствует ли его формат тестовой версии.

3. извините за поздний ответ. как-то не заметил этого. Я скопировал файл примера отсюда в новый файл и выполнил команду join (обе). видимо, это не сработало. я прикрепил выходные данные od-c work1; карта od-c выше. Я нахожусь на CentOS Linux 7

4. Похоже, что ваш файл содержит окончания строк в стиле DOS. Попробуйте установить dos2unix . Вы можете либо перезаписать исходные файлы напрямую ( dos2unix file1 file2 ), либо создать новые файлы ( dos2unix -n in.file out.file и т.д.). Затем выполните join команду для новых файлов. После этого вам, возможно, потребуется запустить unix2dos mergedfile , чтобы сделать это также в формате DOS

5. Спасибо. проблема решена. Действительно, это была проблема с форматом файла.

Ответ №2:

Использование GNU sort для -s (стабильной сортировки) это может быть то, что вам нужно:

 $ sort -k1,1 -u -s working_file-1 mapping_file
K00001  0.188
K00002
K00003
K00004
K00005  15.97
K00006
K00007
K00008  188.09
 

или, если вы хотите добавить 0 s:

 $ sort -k1,1 -u -s working_file-1 mapping_file |
    awk -v OFS='t' '{print $1, $2 =0}'
K00001  0.188
K00002  0
K00003  0
K00004  0
K00005  15.97
K00006  0
K00007  0
K00008  188.09
 

Если у вас нет сортировки GNU, вы могли бы сделать:

 $ sort -k1,1 -k2,2rn working_file-1 mapping_file |
    awk -v OFS='t' '$1 != p{print $1, $2 0; p=$1}'
K00001  0.188
K00002  0
K00003  0
K00004  0
K00005  15.97
K00006  0
K00007  0
K00008  188.09
 

Комментарии:

1. Исправлено. Цель файла сопоставления состоит в том, что у меня есть куча рабочих файлов со случайными значениями K0 (все в диапазоне от K00001 до K25804). Некоторые из K0, присутствующих в одном рабочем файле, отсутствуют в другом. Я хочу присоединиться к этой группе рабочих файлов, добавив 0 к отсутствующим K0, чтобы получить единую таблицу.

2. мой Баш выдал ошибку "Изолированный символ в блоке: недопустимая спецификация блока "1,1 u"". при использовании sort-k1,1u-s working_file-1 сопоставление файла

3. Возможно -k1,1u , так и должно быть -k1,1 -u . Хотя теоретически это может работать с любым типом POSIX , который имеет -s , POSIX, похоже, не определяет, какая из нескольких "уникальных" строк будет напечатана. Версии GNU и FreeBSD, похоже, работают так, как ожидает Эд, но busybox все равно печатает обе строки (что, я думаю, может быть ошибкой).

4. Вы не имеете -s в виду, что это для стабильного сорта? -u предназначен для унификации - это то, что posix, похоже, не определяет, выбирая, какую "уникальную" строку выводить, когда они не идентичны (как в этом случае).

5. кстати, информационная страница GNU coreutils подразумевает -s , что она избыточна при -u использовании (и исходный код, похоже, согласен). в комментариях источника сбивчиво говорится как "Будет выведена только последняя из последовательности одинаковых строк", так и "выведите только первую из идентичной серии строк".

t' -1 1 -2 1 -a 1 -e 0 -o 0,2.2 map work2 >merged3
чтобы создать «merged3», как:


(примечание: снова stackoverflow отображает вкладку в виде пробелов)

Комментарии:

1. Действительно спасибо, что так красиво все изложил. но почему-то это не сработало. с помощью join -1 1 -2 1 -a 1 -e 0 -o 0,2.2 работа с картой 1 > слияние2 вывод-K00001 K00002 K00003 …. с соединением -t $’t’ -1 1 -2 1 -a 1 -e 0 -o 0,2.2 работа с картой 2 >>объединение3 вывод-K00001 0 K00002 0 K00003 0 …..

2. @Shail какую ОС вы используете? Возьмите ваши новые примеры из вашего вопроса и запустите команду join — это работает? Если нет, запустите od -c work1; od -c map новые файлы, которые вы только что создали, и добавьте выходные данные в свой вопрос. Если это работает, попробуйте od -c realwork | less или что-то в вашем реальном файле и проверьте, соответствует ли его формат тестовой версии.

3. извините за поздний ответ. как-то не заметил этого. Я скопировал файл примера отсюда в новый файл и выполнил команду join (обе). видимо, это не сработало. я прикрепил выходные данные od-c work1; карта od-c выше. Я нахожусь на CentOS Linux 7

4. Похоже, что ваш файл содержит окончания строк в стиле DOS. Попробуйте установить dos2unix . Вы можете либо перезаписать исходные файлы напрямую ( dos2unix file1 file2 ), либо создать новые файлы ( dos2unix -n in.file out.file и т.д.). Затем выполните join команду для новых файлов. После этого вам, возможно, потребуется запустить unix2dos mergedfile , чтобы сделать это также в формате DOS

5. Спасибо. проблема решена. Действительно, это была проблема с форматом файла.

Ответ №2:

Использование GNU sort для -s (стабильной сортировки) это может быть то, что вам нужно:


или, если вы хотите добавить 0 s:


Если у вас нет сортировки GNU, вы могли бы сделать:


Комментарии:

1. Исправлено. Цель файла сопоставления состоит в том, что у меня есть куча рабочих файлов со случайными значениями K0 (все в диапазоне от K00001 до K25804). Некоторые из K0, присутствующих в одном рабочем файле, отсутствуют в другом. Я хочу присоединиться к этой группе рабочих файлов, добавив 0 к отсутствующим K0, чтобы получить единую таблицу.

2. мой Баш выдал ошибку «Изолированный символ в блоке: недопустимая спецификация блока «1,1 u»». при использовании sort-k1,1u-s working_file-1 сопоставление файла

3. Возможно -k1,1u , так и должно быть -k1,1 -u . Хотя теоретически это может работать с любым типом POSIX , который имеет -s , POSIX, похоже, не определяет, какая из нескольких «уникальных» строк будет напечатана. Версии GNU и FreeBSD, похоже, работают так, как ожидает Эд, но busybox все равно печатает обе строки (что, я думаю, может быть ошибкой).

4. Вы не имеете -s в виду, что это для стабильного сорта? -u предназначен для унификации — это то, что posix, похоже, не определяет, выбирая, какую «уникальную» строку выводить, когда они не идентичны (как в этом случае).

5. кстати, информационная страница GNU coreutils подразумевает -s , что она избыточна при -u использовании (и исходный код, похоже, согласен). в комментариях источника сбивчиво говорится как «Будет выведена только последняя из последовательности одинаковых строк», так и «выведите только первую из идентичной серии строк».